Collection 接口
Collection是接口的接口,实现Collection 接口的List和Set接口。下面展示collection的方法。
List 接口
实现List接口的实现类有:LinkedList【链表】 ArrayList【数组】 Vector【向量】 。
小结:
ArrayList是数组,(通过array就看出来了),我们都知道:数组查询快,增删慢。
LinkList是链表,我们都知道:链表查询慢,增删快。
Vector底层也是数组,他优势在于线程安全,但效率低。
也许你想说:这我不知道啊。
我来告诉你原因:数组时连续的一块内存,用下标可以随机访问,但在增加删除时,必然导致其他下标的元素整体错位移动。
而链表是通过指针连接的多个分散的节点,访问只能从头顺序依次遍历,但删除时,只需要把目标节点的前一个节点和后一个节点相连就好了。
新增时:只需将新增结点插入到这个位置的前后节点之间,用指针将把门连接起来就好,不涉及其他节点的整体移动。
Set 接口
(1)HashSet
哈希表实现,数据唯一且无序,元素的唯一性是靠所存储元素类型是否重写hashCode()和equals()方法来保证的。
确定唯一性的比较过程:
1、hash()算法函数生成一个int类型hashCode散列值,去和集合中已有元素的hashCode值比较,不相等则说明是新元素。
2、若hashCode相等,也不能说明是同一元素,因为存在不同数据的hashCode相同的情况(极个别)。然后会调用equals()方法判断两个对象的内容是否相等,如果内容不相等,那么就是不同的对象,此时就要采用哈希的解决地址冲突算法找到这个对象的该去的存储位置。
注意:所以要存入HashSet的集合对象中的自定义类必须覆盖hashCode(),equals()两个方法,才能保证集合中元素不重复
(2)LinkedHashSet
采用链表+哈希表共同实现,数据唯一且有序,线程不安全,效率高。
(3)TreeSet
采用二叉树来实现,数据唯一且有序,唯一性同样需要重写hashCode和equals()方法,比较器排需要在TreeSet初始化是时候传入一个实现Comparator接口的比较器对象,或者采用匿名内部类的方式new一个Comparator对象,重写里面的compare()方法;
使用场景分析:
Map 接口
Map用于保存具有映射关系的数据,Map里保存着两组数据:key和value,它们都可以使任何引用类型的数据,但key不能重复。所以通过指定的key就可以取出对应的value。
HashMap和HashTable的比较
TreeMap
小结:
HashMap 非线程安全,基于哈希表实现。使用HashMap要求添加的键类明确定义了hashCode()和equals(),为了优化HashMap空间的使用,您可以调优初始容量和负载因子。
TreeMap:非线程安全基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。
HashTable :线程安全
HashMap:适用于Map中插入、删除和定位元素。
Treemap:适用于按自然顺序或自定义顺序遍历键(key)。
线程安全集合类与非线程安全集合类:
LinkedList、ArrayList、HashSet是非线程安全的,Vector是线程安全的;
HashMap是非线程安全的,HashTable是线程安全的;
StringBuilder是非线程安全的,StringBuffer是线程安全的。
补充:最后说一下常问到的Set和Map怎么遍历?
遍历Map:在for-each循环中使用entries来遍历
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
}
迭代器遍历Set:
Set<String> set = new HashSet<String>();
Iterator<String> it = set.iterator();
while (it.hasNext()) {
String str = it.next();
System.out.println(str);
}