文章目录
Java集合框架
- Java 集合,也称作容器,主要是由两大接口派生出来的:Collection 和 Map。
- Collection 存放单一元素。Map 存放 key-value 键值对。
Collection
1、List:
- ArrayList: Object[] 数组
- LinkedList: 双向链表
2、Set
- HashSet:基于 HashMap 实现
- LinkedHashSet: 是 HashSet 的子类,内部通过 LinkedHashMap 实现。
- TreeSet:有序,唯一,红黑树(自平衡的排序二叉树)
3、Queue
- PriorityQueue: Object[] 数组来实现二叉堆
- ArrayQueue: Object[] 数组 + 双指针
Map
1、HashMap
- 底层由数组和链表或红黑树组成。
- 当链表长度大于阈值(默认为 8)时,将链表转化为红黑树,以减少搜索时间。
- 如果当前数组的长度小于 64,那么会选择先进行数组扩容
2、LinkedHashMap
- LinkedHashMap 继承自 HashMap,底层由数组和链表或红黑树组成。
- 增加了一条双向链表,使得上面的结构可以保持键值对的插入顺序。
3、Hashtable
- 数组+链表组成的,数组是 Hashtable 的主体,链表则是主要为了解决哈希冲突而存在
4、TreeMap
- 红黑树(自平衡的排序二叉树)
List、Set、Queue、Map 区别
- List: 存储的元素是有序的、可重复的。
- Set: 存储的元素是无序的、不可重复的。
- Queue: 按特定的排队规则来确定先后顺序,存储的元素是有序的、可重复的。
- Map: key 是无序的、不可重复的,value 是无序的、可重复的,每个键最多映射到一个值。
ArrayList、LinkedList
- ArrayList 和 LinkedList 都是不同步的,也就是不保证线程安全;
- ArrayList 底层使用的是 Object 数组;LinkedList 底层使用的是 双向链表 数据结构。
- ArrayList 采用数组存储,插入和删除元素的时间复杂度受元素位置的影响。 末尾add是 O(1),指定位置O(n-i)。
- LinkedList 采用链表存储,插入或者删除元素不受元素位置的影响,头尾插入 O(1),指定位置O(n),因为需要先移动到指定位置再插入。
- LinkedList 不支持高效的随机元素访问,而 ArrayList(实现了RandomAccess接口) 支持。
- ArrayList 的空 间浪费主要体现在在 list 列表的结尾会预留一定的容量空间,而 LinkedList 的空间花费则体现在它的每一个元素都需要消耗比 ArrayList 更多的空间(因为要存放直接后继和直接前驱以及数据)。
- 不会使用到 LinkedList,几乎都可以使用 ArrayList 来代替。
1、ArrayList
- 数组实现,可以随机访问,查找快。
- 物理连续性,增删中间元素需移动后续元素。
指定 index 添加数据,就需要拷贝 index 后面的数据后移一位。- 动态数组,初始化时是一个空数组,在第一次 add 时设置初始容量为 10,每次扩容都增加到原来的 1.5 倍。
2、LinkedList
- 链表实现,查找元素需从头访问。
- 增删快。
3、Vector
- 数组实现
- 弃用,线程安全,但是太多synchronized,效率低
4、ArrayList和Vector区别
- Vector线程安全
- 扩容机制,ArrayList增量右移一位即/2,新容量是原容量1.5倍。Vector新容量是2倍。
5、Stack
- 弃用,使用ArrayDeque实现
功能 | 方法 | ArrayList | LinkedList |
---|---|---|---|
增 | add(E e) | O(1) | O(1) |
删 | remove(int index) | O(n) | O(n) |
改 | set(int index, E e) | O(1) | O(n) |
查 | get(int index) | O(1) | O(n) |
ArrayList 的扩容机制
HashSet、LinkedHashSet 、TreeSet
- 都不是线程安全的。
- HashSet 的底层数据结构是哈希表(基于 HashMap 实现),主要特点是无序的,基本操作都是 O(1) 的时间复杂度。
- LinkedHashSet 的底层数据结构是链表和哈希表(HashSet + LinkedList ),元素的插入和取出顺序满足 FIFO。
- TreeSet 底层数据结构是红黑树,元素是有序的,排序的方式有自然排序和定制排序。 用于支持对元素自定义排序规则的场景。
Queue 、Deque
- Queue 是单端队列,只能从一端插入元素,另一端删除元素,实现上一般遵循 先进先出(FIFO) 规则。
- Deque 是双端队列,在队列的两端均可以插入或删除元素。
ArrayDeque 、 LinkedList
- ArrayDeque 和 LinkedList 都实现了 Deque 接口,两者都具有队列的功能。
- ArrayDeque 是基于可变长的数组和双指针来实现,而 LinkedList 则通过链表来实现。
- ArrayDeque 不支持存储 NULL 数据,但 LinkedList 支持。
- ArrayDeque 插入时可能存在扩容过程, 不过均摊后的插入操作依然为 O(1)。
- LinkedList 不需要扩容,但是每次插入数据时均需要申请新的堆空间,均摊性能相比更慢。
- 选用 ArrayDeque 来实现队列要比 LinkedList 更好。
- ArrayDeque 也可以用于实现栈。
PriorityQueue
- PriorityQueue 利用了二叉堆的数据结构来实现的,底层使用可变长的数组来存储数据
- PriorityQueue 通过堆元素的上浮和下沉,实现了在 O(logn) 的时间复杂度内插入元素和删除堆顶元素。
- PriorityQueue 是非线程安全的,且不支持存储 NULL 和 non-comparable 的对象。
- PriorityQueue 默认是小顶堆,但可以接收一个 Comparator 作为构造参数,从而来自定义元素优先级的先后。
1、Queue两组API,功能相同,用法区别:
功能 | 抛异常 | 返回值 |
---|---|---|
增 | add(E e) | offer(e) |
删 | remove() | poll() |
查 | element() | peek() |
2、 Deque双端队列,针对两端:
功能 | 抛异常 | 返回值 |
---|---|---|
增 | addFirst(e)/ addLast(e) | offerFirst(e)/ offerLast(e) |
删 | removeFirst()/ removeLast() | pollFirst()/ pollLast() |
查 | getFirst()/ getLast() | peekFirst()/ peekLast() |
3、实现类:LinkedList、ArrayDeque、PriorityQueue
- 普通队列:LinkedList、ArrayDeque
- 优先队列:PriorityQueue
- 栈:ArrayDeque
- LinkedList、ArrayDeque区别
①ArrayDeque 是一个可扩容的数组,LinkedList 是链表结构;
②ArrayDeque 里不可以存 null 值,但是 LinkedList 可以;
③ArrayDeque 在操作头尾端的增删操作时更高效,但是 LinkedList 只有在当要移除中间某个元素且已经找到了这个元素后的移除才是 O(1) 的;
④ArrayDeque 在内存使用方面更高效。
所以,只要不是必须要存 null 值,就选择 ArrayDeque 吧!
Collection
常用API,操作集合CRUD(Create, Read, Update, and Delete):
boolean add(E e);
boolean addAll(Collection<? extends E> c);
boolean remove(Object o);
boolean removeAll(Collection<?> c);
boolean contains(Object o);
boolean containsAll(Collection<?> c);
boolean isEmpty();
int size();
Object[] toArray(); // 集合转数组
Comparator、Comparable
- Comparator :Collections.sort()重写Comparator的compare实现。
Collections.sort(arrayList, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1);
}
});
- Comparable:接口,重写compareTo的实现。
public class Person implements Comparable<Person> {
@Override
public int compareTo(Person o) {
if (this.age > o.getAge()) {
return 1;
}
if (this.age < o.getAge()) {
return -1;
}
return 0;
}
}
Collections方法
参考
https://mp.weixin.qq.com/s?__biz=MzAwNDA2OTM1Ng==&mid=2453144514&idx=2&sn=3b14fa92bd3d129d5c60a2eea0c5869f&scene=21#