Java常用集合笔记

最近事情比较少,闲暇之余温习巩固一下Java的一些基础知识,并做一些笔记,

Java常用集合,

主要参考的这篇文章:Java常用集合

ArrayList/Vertor

1. ArrayList 的主要消耗是数组扩容以及在指定位置添加数据,在日常使用时最好是指定大小,尽量减少扩容。更要减少在指定位置插入数据的操作。
2. 使用了 transient 修饰,可以防止被自动序列化。由于 ArrayList 是基于动态数组实现的,所以并不是所有的空间都被使用。 ArrayList 只序列化了被使用的数据。
3. 当对象中自定义了 writeObject 和 readObject 方法时,JVM 会调用这两个自定义方法来实现序列化与反序列化。
4. Voctor 也是实现于 List 接口,底层数据结构和 ArrayList 类似,也是一个动态数组存放数据。不过是在 add() 方法的时候使用 synchronize 进行同步写数据,但是开销较大,所以 Vector 是一个同步容器并不是一个并发容器。

LinkedList

1. LinkedList 底层是基于双向链表实现的,也是实现了 List 接口
2. LinkedList 插入,删除都是移动指针效率很高。
3. 查找需要进行遍历查询,效率较低。

HashMap

1. HashMap 底层是基于数组和链表实现的。其中有两个重要的参数:容量、负载因子,容量的默认大小是 16,负载因子是 0.75,当 HashMap 的 size > 16*0.75 时就会发生扩容(容量和负载因子都可以自由调整)。发生扩容时会对所有元素进行rehash
2. put 方法:首先会将传入的 Key 做 hash 运算计算出 hashcode,然后根据数组长度取模计算出在数组中的 index 下标。由于在计算中位运算比取模运算效率高的多,所以 HashMap 规定数组的长度为 2^n 。这样用 2^n - 1 做位运算与取模效果一致,并且效率还要高出许多。由于数组的长度有限,所以难免会出现不同的 Key 通过运算得到的 index 相同,这种情况可以利用链表来解决,HashMap 会在 table[index]处形成链表,采用头插法将数据插入到链表中。
3. get 方法:和 put 类似,也是将传入的 Key 计算出 index ,如果该位置上是一个链表就需要遍历整个链表,通过 key.equals(k) 来找到对应的元素。
4. 在并发环境下使用 HashMap 容易出现死循环。所以 HashMap 只能在单线程中使用,并且尽量的预设容量,尽可能的减少扩容。
5. 在 JDK1.8 中对 HashMap 进行了优化: 当 hash 碰撞之后写入链表的长度超过了阈值(默认为8),链表将会转换为红黑树。
	### 红黑树
		1. 红黑树,一种二叉查找树,但在每个结点上增加一个存储位表示结点的颜色,可以是Red或Black。
		2. 通过对任何一条从根到叶子的路径上各个结点着色方式的限制,红黑树确保没有一条路径会比其他路径长出俩倍,因而是接近平衡的。

HashSet

1. HashSet 是一个不允许存储重复元素的集合。HashSet 的原理比较简单,几乎全部借助于 HashMap 来实现的。

LinkedHashMap

1. LinkedHashMap 其实就是对 HashMap 进行了拓展,使用了双向链表来保证了顺序性。
2. LinkedHashMap 的排序方式有两种:根据写入顺序排序。根据访问顺序排序。其中根据访问顺序排序时,每次 get 都会将访问的值移动到链表末尾,这样重复操作就能得到一个按照访问顺序排序的链表。
posted @ 2018-07-18 19:20  ACBingo  阅读(275)  评论(0编辑  收藏  举报