Java中各容器集合
Java中各容器集合
由上图可见容器类向下延伸出Set(继承了Collection)、List(继承了Collection);而Map容器自成一线,那么他们之间有什么区别和联系呢?废话不多说 直接看下表:
名称 | 分类 | 作用 | 是否线程安全 |
---|---|---|---|
ArrayList | 底层由数组结构实现,数组在内存中的存储顺序是连续的,对集合中的元素可以进行快速访问,更适合用来随机查询数据。 | 否 | |
List | LinkedList | 底层由双向链表结构实现,通过节点来存储下一个元素的位置,对集合中的元素可以方便的增加与删除,更适合用于大量修改。 | 否 |
Vector | Vector与ArrayList的区别就是Vector是线程安全的集合,在需要线程安全而且对效率要求比较低的情况下,使用Vector | 是 | |
HashMap | 继承自AbstractMap的一个散列表,key-value的形式存储数据,在HashMap中,key-value总是会当做一个整体来处理,系统会根据hash算法来来计算key-value的存储位置,如果位置相同时(所谓的hash冲突),就会用链表存储,当冲突数据过多时(链表中的数据>8个)则用红黑树存储。 | 否 | |
Hashtable | 于HashMap类似但是所有方法都实现了同步,且不能有null键和值(HashMap可以接受null键和值),注:Hashtable不推荐使用; | 是 | |
Map | ConcurrentHashMap | 自JDK1.5后为解决线程安全问题推出java.util.concurrent包,ConcurrentHashMap是该包的产物之一,效率比Hashtable高,并发性比hashmap好。结合了两者的特点。 | 是 |
LinkedHashMap | LinkedHashMap内部多了一个双向循环链表的维护,该链表是有序的,可以按元素插入顺序或元素最近访问顺序(LRU)排列,简单地说:LinkedHashMap=散列表+循环双向链表 | 否 | |
TreeMap | TreeMap基于红黑树(二叉树),是一个有序的Key-Value集合,HashMap通常比TreeMap快一点(树和哈希表的数据结构使然),建议多使用HashMap,在需要排序的Map时候才用TreeMap。 | 否 | |
weakHashMap | weakHashMap它是一个“弱键”,它的Key值和Value都可以是null,而且其Map中如果这个Key值指向的对象没被使用,此时触发了GC(Garbage Collection,垃圾收集,垃圾回收机制),该对象就会被回收掉的。 | 否 | |
HashSet | 相对无序存储,不可以存储相同元素(排重),每个对象的hashCode值是唯一的,添加数据时首先会调用hashCode()方法判断hashCode值,如果相同再调用其equals()方法匹配重复元素,如果元素相同则覆盖之前的元素。 | 否 | |
Set | LinkedHashSet | 相对HashSet来说,LinkedHashSet存储结构是一个双向链表,因此它存储的元素是有序的,其遍历也是按照插入顺序来。 | 否 |
TreeSet | TreeSet类不仅实现了Set接口,还实现了java.util.SortedSet接口,从而保证在遍历集合时按照递增的顺序获得对象。遍历对象时可能是按照自然顺序递增排列,所以存入用TreeSet类实现的Set集合的对象必须实现Comparable接口;也可能是按照指定比较器递增排列,即可以通过比较器对用TreeSet类实现的Set集合中的对象进行排序。 | 否 |
- 基于底层不同List、Set以及Map三者的主要区别:
List接口存储一组不唯一(可以有多个元素引用相同的对象),有序的对象;
Set不允许重复的集合、不会有多个元素引用相同的对象;
Map使用键值对存储、Map会维护与Key有关联的值、两个Key可以引用相同的对象,但Key不能重复。
- HashMap 和 Hashtable 有什么区别:
存储:HashMap 运行 key 和 value 为 null,而 Hashtable 不允许。
线程安全:Hashtable 是线程安全的,而 HashMap 是非线程安全的。
推荐使用:在 Hashtable 的类注释可以看到,Hashtable 是保留类不建议使用,推荐在单线程环境下使用 HashMap 替代,如果需要多线程使用则用 ConcurrentHashMap 替代。
- HashMap 和 TreeMap的区别:
对于在 Map 中插入、删除、定位一个元素这类操作,HashMap 是最好的选择,因为相对而言 HashMap 的插入会更快,但如果你要对一个 key 集合进行有序的遍历,那 TreeMap 是更好的选择。
- HashMap 的实现原理:
HashMap 基于 Hash 算法实现的,我们通过 put(key,value)存储,get(key)来获取。当传入 key 时,HashMap 会根据 key. hashCode() 计算出 hash 值,根据 hash 值将 value 保存在 bucket 里。当计算出的 hash 值相同时,我们称之为 hash 冲突,HashMap 的做法是用链表和红黑树存储相同 hash 值的 value。当 hash 冲突的个数比较少时,使用链表否则使用红黑树。
- HashSet 的实现原理:
HashSet 是基于 HashMap 实现的,HashSet 底层使用 HashMap 来保存所有元素,因此 HashSet 的实现比较简单,相关 HashSet 的操作,基本上都是直接调用底层 HashMap 的相关方法来完成,HashSet 不允许重复的值。
- ArrayList 和 LinkedList 的区别:
数据结构实现:ArrayList 是动态数组的数据结构实现,而 LinkedList 是双向链表的数据结构实现。
随机访问效率:ArrayList 比 LinkedList 在随机访问的时候效率要高,因为 LinkedList 是线性的数据存储方式,所以需要移动指针从前往后依次查找。
增加和删除效率:在非首尾的增加和删除操作,LinkedList 要比 ArrayList 效率要高,因为 ArrayList 增删操作要影响数组内的其他数据的下标。
一句话概括这么情况下使用:
- List:
查询多使用ArrayList,插入删除用LinkedList,不求效率高要求线程安全时用Vector;
- Set:
无序HashSet,有序HashSet,排序TreeSet;线程安全需要通过ConcurrentHashMap进行转换(谷歌已推出ConcurrentHashSet即newConcurrentHashSet);
- Map:
常用的HashMap,有序用LinkedHashMap,排序用TreeMap,线程安全用ConcurrentHashMap,Hashtable切记要少用,GC数据用weakHashMap;