集合框架中有两个顶层接口,一个是Collection,一个是Map
Collection(用于存储一组对象)
下面这张图是我截取的Collection接口的一些常用继承关系。看一下对这个顶级接口有一个简单的了解。
- Vector
- jdk1.0就存在了。底层是数组结构的。可变长度数组,原理:一旦原数组长度不够,会创建新数组,将原数组的元素复制到新数组中,并将新元素添加到新数组中。Vector是同步的。
- LinkedList
- 实现了List接口,允许null元素。此外LinkedList提供额外的get,remove,addFirst/Last方法在LinkedList的首部或尾部。这些操作使LinkedList可被用作堆栈(stack),队列(queue)或双向队列(deque)。
- 注意LinkedList没有同步方法。如果多个线程同时访问一个List,则必须自己实现访问同步。一种解决方法是在创建List时构造一个同步的List:
List list = Collections.synchronizedList(new LinkedList(...));
- ArrayList
- 实现了可变大小的数组。它允许所有元素,包括null。ArrayList没有同步。 size,isEmpty,get,set方法运行时间为常数,也就是时间复杂度是O(1)。但是add方法开销为分摊的常数,添加n个元素需要O(n)的时间。其他的方法运行时间为线性。
- 每个ArrayList实例都有一个容量(Capacity),不设置的话为10,即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法为原大小的1.5倍。当需要插入大量元素时,在插入前可以调用ensureCapacity方法来增加ArrayList的容量以提高插入效率。
- ArrayList查找快,LinkList增加删除快(底层双链表)
Set集不允许重复元素。null最多有一个
- HashSet底层数据结构是哈希表,是不同步的。如果存自定义对象,
- 不重写equals()方法,重写了hashCode()。我们重写的hashCode,万一重写的出现了相同的hashCode。就存不进去了,如果调用父类的,JVM返回的和地址值有关。所有对象的hashCode都不同。不允许重复元素等于形同虚设。
- 重写equals()方法,不重写hashCode()。我们总有自己的逻辑是判断元素是否相等。不重写hashCode,返回的默认哈希值和地址值有关。不允许重复元素等于形同虚设。
- 重写equals()方法,重写hashCode()。我们通过拿对象的一些属性来判断返回哈希值,甚至可以默认返回1,2,3等。重写equals(),自定义自己的判断相等方法,存入元素。
- 存储值先判断hashCode是否相同,相同调用equals,不同直接判断。
- TreeSet
- 二叉树数据结构,也叫红黑树
- 存储的对象必须实现Comparable接口,根据返回值判断是否相等,如果返回0了,就不存。
- 如果适中返回1 ,就是一直往右子树上面添加。按存入的顺序读出来。
- 请注意:必须小心操作可变对象(Mutable Object)。如果一个Set中的可变元素改变了自身状态导致Object.equals(Object)=true将导致一些问题。
Map (用于存储具备对应关系的键和值)
- 常用遍历方法
Map<K, V> map = new HashMap<K, V>();
Set<Entry<K, V>> entrySet = map.entrySet();
Set<K> keySet = map.keySet();
set.iterator();
Entry是Map的一个内部接口。
Collection<V> values = map.values();
Iterator<V> iterator = values.iterator();
- 哈希表是底层的数据结构
- HashTable
- 是线程同步的,不允许null作为键,作为值
- HashMap
- 是线程不同步的,允许null作为键,作为值
- TreeMap
- 可以对Map集合中的键进行指定顺序的排序。默认为自然顺序。
- 底层是二叉树