Java集合(JDK1.8 )

392 阅读2分钟

一、ArrayList VS. LinkedList

1.1 底层数据结构

ArrayList: 数组(初始容量为10,扩容为 max{1.5倍,需要的容量}) LinkedList: 双向链表(不需要扩容)

1.2 查改效率

ArrayList: O(1) 随机访问
(Collection中的binarySearch对实现了RandomAccess的对象使用index-for循环get遍历比Iterator快,详细:blog.csdn.net/qq_42595077…

LinkedList:O(n) 可选择从前或从后查询 (LinkedList使用Iterator比For循环get遍历快)

1.3 增删效率

如果增删在尾部,ArrayList、LinkedList是O(1) (ArrayList更快)
如果增删在头部,LinkedList更快
如果增删在中间,ArrayList O(n)需要移动后面的所有元素,而LinkedList找到索引位置后改变节点指向

但是还需要注意ArrayList可能会涉及到扩容

1.4 空间占用

LinkedList 每个Node需要保存prev和next

二、HashSet

2.1 底层

HashMap :数组+链表+红黑树 存储键值对
HashSet: HashMap (Key为集合元素,value全都是一个object PRESENT)

2.2 查询(注意没有get方法)

contains(Object o)调用map的containsKey(o);

2.3 增删

add方法调用map的put方法
remove方法调用map的remove方法 返回true / false;

2.4 遍历

直接调用map的keySet的迭代器

和HashMap的比较

HashSet实现Set接口,存储对象,删除返回true / false
HashMap实现Map接口,存储键值对, 删除返回value

三、HashMap

3.1 底层:

数组+链表+红黑树

3.2 put流程

3.3 HashMap为什么线程不安全

JDK1.7是因为链表头插造成在多线程扩容时顺序翻转产生死循环链表 JDK1.8后采用尾插不会造成死循环,但会造成数据丢失问题:当table[i] == null时,正好有多线程插入,线程1和2都判断了可以直接插入,而这时2被挂起,1插入之后,2又直接覆盖掉1的数据。

3.4 ConcurrentHashMap vs. HashMap vs. Hashtable

区别ConcurrentHashMapHashMapHashtable
线程安全性线程安全线程不安全线程安全
键值可否为NULL不能不能
求下标方法hash&(len-1)hash&(n-1)hashCode%len
扩容先检查、*2插入后检查、*2先检查、 *2+1
初始容量161611

四、TreeMap

  • 底层:红黑树
  • 使用场景:需要key排序或者构造比较器自定义排序,可以保证遍历顺序和插入顺序一致
  • 缺点:TreeMap 遍历 O(logn)