常用集合与分类
-
Collection
- List:按顺序保存元素。
- ArrayList:数组实现,随机访问性能好。
- LinkedList:双向链表实现,插入删除性能好。
- Set:不添加重复元素。
- HashSet:快速查找元素,由HashMap实现。元素须定义
hashCode()
和equals()
方法。 - LinkedHashSet:快速查找元素+链表维护读写顺序,由LinkedHashMap实现。元素须定义
hashCode()
和equals()
方法。 - TreeSet:有序Set,由TreeMap实现。元素须实现
Comparable
接口。
- HashSet:快速查找元素,由HashMap实现。元素须定义
- Queue:队列,先进先出。
- Deque:双端队列 (double-ended queue)。
- ArrayDeque:数组实现,头尾指针在数组中循环移动,性能好。
- LinkedList:双向链表实现。
- PriorityQueue:插入后排序元素,使用堆实现,队列头部默认为最小的元素(自然顺序)。
- Deque:双端队列 (double-ended queue)。
- List:按顺序保存元素。
-
Map
- HashMap:散列表实现,根据Key存取关联的Value。
- LinkedHashMap:HashMap+双向链表维护读写顺序。默认是维护最后写入的顺序,也可以指定为读取排序 (accessOrder),使用LRU算法实现。
- TreeMap:根据key进行排序,使用红黑树实现。插入时找到key对应的节点并替换value,没找到则生成新节点。
补充:堆和二叉搜索树的区别(红黑树也是二叉搜索树):
- 堆:为排序而设计。查找需要遍历,性能差。
- 二叉搜索树:为查找而设计。
Java 集合框架类图
黄色为接口,绿色为抽象类,蓝色为具体类。虚线箭头表示实现关系,实线箭头表示继承关系。
Collection
Map
ArrayList
ArrayList内部使用数组实现。
1 | ArrayList<String> list = new ArrayList<>(); |
LinkedList:List、Stack、Deque
LinkedList内部使用链表实现,实现了List、Stack、Deque接口。
-
addFirst()
-
addLast()
=add()
=offer()
-
getFirst()
=element()
,返回元素或抛异常;peek()
,返回元素或null。 -
removeFirst()
=remove()
,删除元素或抛异常;poll()
,删除元素或返回null。 -
removeLast()
1 | LinkedList<String> list; |
List转数组
1 | List<Integer> list; |
Arrays
Arrays.asList
工具方法 Arrays.asList()
生成的是一个不可修改的List,其类型为 Arrays.ArrayList
。
1 | List list = Arrays.asList(1,2,3); |
Arrays.sort与Comparator.compare
1 | int[] array = new int[]{3,1,2}; |
1 | // 使用Comparator,升序 |
LinkedHashMap实现LRU
1 | import java.util.LinkedHashMap; |
Collections.synchronizedXxx
生成Collection的同步对象。
1 | // collectiontopics/Synchronization.java |
Fail Fast / ConcurrentModificationException
在使用Iterator读取过程中,不能修改Collection,否则会抛出ConcurrentModificationException异常。可以使用ConcurrentHashMap、CopyOnWriteArrayList、CopyOnWriteArraySet 避免异常。
1 | // collectiontopics/FailFast.java |
equals和hashcode方法
1、使用自己的类作为HashMap的键,必须同时重载 hashCode()
和 equals()
。
2、Map原理:Key ==> 散列函数 ==> key.hashCode() ==> Bucket数组 => Bucket (桶,List实现) ==> key.equals() ==> 找到Value。
3、hashCode()
设计:
- 速度快
- 分布均匀
- 对象未改变的情况下,多次调用返回值一致
- 可以重新创建新的Key,使其和之前Key的hashCode相同(不然Key对象被回收了之后就没法取出对应的Value了)
4、多个Object联合计算HashCode,可以使用Objects工具方法
1 |
|
1 | public final class Objects { |
HashMap原理与调优
HashMap内部有一个Node数组 Node<K,V>[] table
,也称为桶,每个Node又是一个链表节点。
1 | table [ |
参数
- Capacity:容量,即桶的数量
- Initial Capacity:初始容量
- Size:尺寸
- Load Factor:负载因子 = Size / Capacity
实现
-
HashMap的容量为2的次方(这样计算桶的Index时,可以用位运算代替除法)。
-
当负载因子超过0.75时,执行rehashing操作,将容量扩展为2倍。
-
轻负载,插入和查询性能好(但会减慢迭代器遍历,因为table太长)。
调优方法:
- 如果提前知道条目个数,直接创建容量合适的 HashMap。