Java基础——集合框架
一、集合
Java集合类存放于 java.util 包中,是一个用来存放对象的容器。Java 集合框架主要包括两种类型的容器,一种是集合(Collection),存储一个元素集合,另一种是图(Map),存储键/值对映射。
1)集合中只能存放对象;
2)集合存放的是对象的引用,对象本身仍在堆内存中;
3)集合可以存放不同类型、不同数量的数据类型(Map)。
二、集合框架
图片来源:http://blog.csdn.net/u010887744/article/details/50575735
高清图地址:https://img-blog.csdn.net/20160124221843905
三、集合详解
Collection集合框架
顶层接口:
public interface Iterable<T> {
/**
* 返回类型 T元素的迭代器。
*/
Iterator<T> iterator();
/**
* 执行给定的操作的每个元素 Iterable直到所有的元素都已经被处理或行动将抛出一个异常。
* @since 1.8
*/
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
/**
* 在Iterable描述的元素上创建一个spliterator
* @since 1.8
*/
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
迭代器接口:
public interface Iterator<E> {
/**
* 如果仍有元素可以迭代,则返回 true。
*/
boolean hasNext();
/**
* 返回迭代的下一个元素
*/
E next();
/**
* 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。
*/
default void remove() {
throw new UnsupportedOperationException("remove");
}
/**
* 为每个剩余元素执行给定的操作,直到所有的元素都已经被处理或行动将抛出一个异常。
* @since 1.8
*/
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
核心接口:
public interface Collection<E> extends Iterable<E> {
..........
}
子接口:
1)、List<E>:有序,可重复,有索引
public interface List<E> extends Collection<E> {
.........
}
实现类:
List<Integer> list1 = new ArrayList<>();
List<Integer> list2 = new LinkedList<>();
List<Integer> list3 = new Vector<>();
ArrayList<E>:ArrayList是基于数组实现的List类,它封装了一个动态的增长的、允许再分配的Object[]数组。
特点:底层数据结构是数组,查询快,增删慢;线程不安全,效率高;
LinkedList<E>:implements List<E>, Deque<E>。实现List接口,能对它进行队列操作,即可以根据索引来随机访问集合中的 元素。同时它还实现Deque接口,即能将LinkedList当作双端队列
特点:底层数据结构是链表,查询慢,增删快;线程不安全,效率高;
Vector<E>:Vector和ArrayList在用法上几乎完全相同,基本被淘汰
特点:底层数据结构是数组,查询快,增删慢;线程安全,效率低,几乎已经淘汰了这个集合;
其他:
Stack:vector提供的字类,用于模拟"栈"这种数据结构(LIFO后进先出)
CopyOnWriteArrayList:
CopyOnWriteArrayList是ArrayList的线程安全的变体,其中的所有可变操作(add, set等)都是对底层数组进行一次新的复制来实现的,相比ArrayList的要慢一些,适用于读多写少的场景 ;
在并发操作容器对象时不会抛出ConcurrentModificationException,并且返回的元素与迭代器创建时的元素是一致的 ;
容器对象的复制需要一定的开销,如果对象占用内存过大,可能造成频繁的YoungGC和Full GC ;
CopyOnWriteArrayList不能保证数据实时一致性,只能保证最终一致性
2)、Set<E>:不可重复,无索引
public interface Set<E> extends Collection<E> {
.........
}
实现类:
Set<Integer> set1 = new HashSet<>();
Set<Integer> set2 = new LinkedHashSet<>();
Set<Integer> set3 = new TreeSet<>();
HashSet<E>:HashSet是Set接口的典型实现,HashSet使用HASH算法来存储集合中的元素,因此具有良好的存取和查找性 能。当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据该 HashCode值决定该对象在HashSet中的存储位置。
HashSet集合判断两个元素相等的标准是两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法的返回值相等
特点:底层数据结构是数组;无序、不可重复;线程不安全;
LinkedHashSet<E>:
特点:底层采用 链表和哈希表的算法,链表保证元素的添加顺序,哈希表保证元素的唯一性;有序、不可重复;线程不安全;
TreeSet<E>:TreeSet是SortedSet接口的唯一实现类,可以确保集合元素处于排序状态
特点:底层使用红黑树算法,擅长于范围查询;有序、不可重复;线程不安全;
3)、Queue<E>:链表结构,先进先出
public interface Queue<E> extends Collection<E> {
...........
}
Map集合框架
key-value 的键值对,key 不允许重复,value 可以;双列
HashMap<K,V>:线程不安全
ConcurrentHashMap<K,V>:线程安全
四、集合遍历
遍历ArrayList
import java.util.*;
/**
* 三种方法都是用来遍历ArrayList集合,第三种方法是采用迭代器的方法,该方法可以不用担心在遍历的过程中会超出集合的长度。
*/
public class Test{
public static void main(String[] args) {
List<String> list=new ArrayList<String>();
list.add("Hello");
list.add("World");
list.add("HAHAHAHA");
//第一种遍历方法使用foreach遍历List
for (String str : list) { //也可以改写for(int i=0;i<list.size();i++)这种形式
System.out.println(str);
}
//第二种遍历,把链表变为数组相关的内容进行遍历
String[] strArray=new String[list.size()];
list.toArray(strArray);
for(int i=0;i<strArray.length;i++) //这里也可以改写为 foreach(String str:strArray)这种形式
{
System.out.println(strArray[i]);
}
//第三种遍历 使用迭代器进行相关遍历
Iterator<String> ite=list.iterator();
while(ite.hasNext())//判断下一个元素之后有值
{
System.out.println(ite.next());
}
}
}
遍历Map
import java.util.*;
public class Test{
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("1", "value1");
map.put("2", "value2");
map.put("3", "value3");
//第一种:普遍使用,二次取值
System.out.println("通过Map.keySet遍历key和value:");
for (String key : map.keySet()) {
System.out.println("key= "+ key + " and value= " + map.get(key));
}
//第二种
System.out.println("通过Map.entrySet使用iterator遍历key和value:");
Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry<String, String> entry = it.next();
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
//第三种:推荐,尤其是容量大时
System.out.println("通过Map.entrySet遍历key和value");
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
}
//第四种
System.out.println("通过Map.values()遍历所有的value,但不能遍历key");
for (String v : map.values()) {
System.out.println("value= " + v);
}
}
}
遍历Set
import java.util.HashSet;
import java.util.Iterator;
public class SetTest {
public static void main(String[] args) {
HashSet<String> sets = new HashSet<>();
sets.add("h");
sets.add("e");
sets.add("l");
sets.add("l");//不可重复
sets.add("0");
//方法一:迭代遍历
for (Iterator<String> iterator = sets.iterator(); iterator.hasNext();){
System.out.println(iterator.next());
}
//输出结果:
/*
0
e
h
l
*/
//可以看出Set集合是不可重复(添加重复操作不会报错)且无序的
//方法二:foreach循环(没有普通for循环方法)
for (String value:sets) {
System.out.println(value);
}
}
}
上一篇: 二叉树的遍历
下一篇: 求问 遇到grails1.01的一个错误