读《Java核心技术 卷1》集合这一章,书本上基本上看的差不多了,但总觉得不太够,就去网上搜搜一些前人写的Java集合的博客,学习学习,以下大部分内容基本上都是参照 Java集合中List,Set以及Map等集合体系详解(史上最全) 写的。集合盘它!
概述
- List,Set,Map都是接口,前两个继承Collection接口,Map为独立接口
- Set下有HashSet,LinkedHashSet,TreeSet
- List下有ArrayList,Vector,LinkedList
- Map下有HashMap,LinkedHashMap,TreeMap,Hashtable
- Collection下还有Queue接口,有PriorityQueue
总结
Collection接口:
List 有序 可重复
ArrayList
优点:底层数据结构是数组,查询快,增删慢
缺点:线程不安全,效率高
Vector
优点:底层数据结构是数组,查询快,增删慢
缺点:线程安全,效率低
LinkedList
优点:底层数据结构是链表,查询慢,增删慢
缺点:线程安全,效率高
Set 无序 唯一
HashSet
优点:底层数据结构是哈希表。(无序,唯一)
如何保证数据唯一性?
依赖两个方法:hashCode()和equals()
LinkedHashSet
优点:底层数据结构是链表和哈希表。(FIFO插入有序,唯一)
1、由链表保证元素有序
2、由哈希表保证元素唯一
TreeSet
优点:底层数据是红黑树。(唯一,有序)
1、如何保证元素排序的呢?
自然排序
比较器排序
2、如何保证元素唯一性的呢?
根据比较的返回值是否是0来决定
针对Collection集合我们到底使用谁呢?
唯一吗?
是:Set
排序吗?
是:TreeSet或LinkedHashSet
否:HashSet
如果你知道是Set,但是不知道是哪个Set,就用HashSet。
否:List
要安全吗?
是:Vector
否:ArrayList或者LinkedList查询多:ArrayList
增删多:LinkedList
如果你知道是List,但是不知道是哪个List,就用ArrayList。
如果你知道是Collection集合,但是不知道使用谁,就用ArrayList。
如果你知道用集合,就用ArrayList。
Map接口:
Map接口有三个比较重要的实现类,分别是HashMap、TreeMap和HashTable
- TreeMap是有序的,HashMap和HashTable是无序的。
- HashTable的方法是同步的,HashMap的方法不是同步的。这是二者的主要区别。
这意味着:
HashTable是线程安全的,HashMap是线程不安全的。
HashMap效率比较高,HashTable效率较低。
如果对同步性或与遗留代码的兼容性没有任何要求,建议使用HashMap。 查看Hashtable的源代码就可以发现,除构造函数外,Hashtable的所有 public 方法声明中都有 synchronized关键字,而HashMap的源码中则没有。
HashTable不允许null值,HashMap允许null值(key和value都允许)。
父类不同:HashMap的父类是AbstractMap,HashTable的父类是Dictionary。
重点问题分析
(一)TreeSet LinkedHashSet HashSet的区别
1、介绍
TreeSet LinkedHashSet HashSet 在Java中都是实现Set的数据结构
- TreeSet的主要功能用于排序
- LinkedHashSet的主要功能用于保证FiFO即有序的集合(先进先出)
- HashSet只是通用的存储数据的集合
2、相同点
都实现了Set Interface
三者都是线程不安全的,如果使用线程安全的,可以使用 Collections.synchronizedSet()
3、不同点
HashSet插入数据最快,其次是LinkedHashSet,最慢的是TreeSet,因为其内部实现排序
HashSet不保证有序,LinkedHashSet保证FIFO即按照插入顺序排序,TreeSet内部实现排序,也可以自定义排序规则
HashSet和LinkedHashSet允许存在null数据,但是TreeSet中插入null数据会报空指针异常
4、代码比较
1 | public static void main(String[] args) { |
输出结果:
1 | hashSet: [A, B, C, D, E] |
(二)TreeSet的引用类型比较
基本类型会自动排序,引用类型需要我们进行配置。
两种方式:
1、自己写一个比较器,在new TreeSet的时候,传入这个比较器对象即可
1 | TreeSet<Person> treeSet = new TreeSet<>(new MyComparator()); |
1 | public class MyComparator implements Comparator<Person> { |
2、引用类实现Comparate接口方法,重写它的CompareTo方法
1 | public class Person implements Comparable<Person> { |