集合类是 Java 应用过程中最为核心的一部分,类似 C++ 的 STL,不仅在刷题的过程中十分常用,在日常工作生活中也常常使用。因此,我将 Java 集合类的内容进行了整理。参考内容在文末给出。
目录
1. 集合容器概念
1.1 基本内容
什么是集合?
- 集合框架:存储数据的容器。集合包括三个内容:接口(用于形成规范)、实现和算法。
- 集合与数组的区别:集合用于封装对象(引用数据类型);集合可以存放个数不确定的对象;集合可以存储不同数据类型的对象。
1.2 常用内容
常用集合类有哪些?
-
所有集合类的父接口:Map 接口和 Collection 接口。
-
-
-
Collection 接口:包含三种子接口 Set, List 和 Queue(注意还有一个 Queue)。
- Set 子接口:无序,无重复,唯一性,只能插入一个 null。实现类有 HashSet, LinkedHashSet, TreeSet。
- List 子接口:有序,可重复,有索引,可以插任意个 null。实现类有 Stack, Vector, ArrayList, LinkedList。
- Queue 子接口:队列。注意,
Stack
是 List 的实现类,而Queue
是接口。实现类有 Deque。
-
Map 接口:下面就是实现类。包含 HashMap, TreeMap, HashTable, LinkedHashMap, ConcurrentHahsMap。
-
注意,Stack、Queue、Map 的位置。Python 中他们仨是并列的,而 Java 不是,Java 中 Stack 是 List 接口的实现类;而 Queue 是 Collection 接口的子接口,实现类是 Deque;Map 是区别于 Collection 的另一个接口,实现类一般是 HashMap。⭐
常用实现类有哪些?
- Collection:
- Set:
- HashSet:基于 HashMap 实现。
- LinkedHashSet:基于 LinkedHashMap 实现。可以记录插入顺序。
- TreeSet:基于 TreeMap 实现。红黑树结构(自平衡排序二叉树)。
- List:
- ArrayList:Object 数组。
- LinkedList:双向循环链表。
- Vector:ArrayList 的线程安全版。
- Stack:栈。
- Queue:
- Deque:队列。
- Set:
- Map:
- HashMap:字典。
- LinkedHashMap:字典,可以记录插入顺序。
- HashTable:HashMap 的线程安全版。
- TreeMap:字典,红黑树。
1.3 面试问题
哪些集合是线程安全的?
- 线程安全的有:Stack, HashTable, Vector(很少用,效率低), Enumeration。
fail-fast 是啥?
- 多线程同时改变集合时的错误检测机制。
怎么让集合不被修改?
- Collections. unmodifiableCollection(Collection c) 创建只读集合。
2. Collection 接口
2.1 Iterator 接口
Iterator 接口是什么?
-
定义:Iterator 接口提供了 Collection 接口的遍历。
-
List<Integer> arrayListA = new ArrayList<>(); Iterator<Integer> it = arrayListA.iterator(); while(it.hasNext()){ System.out.println("Value is %d", it.next()); }
-
特点:Iterator 只能单向遍历,但线程安全。
-
-
Iterator 子类:ListIterator,可以双向遍历。Iterator 可以用于 Set 和 List, ListIterator 只能用于 List。
如何边遍历边删除集合内容?
-
唯一方法:采用 Iterator 遍历,并用 Iterator.remove() 方法删除集合内容。
-
List<Integer> arrayListA = new ArrayList<>(); Iterator<Integer> it = arrayListA.iterator(); while(it.hasNext()){ it.remove(); }
Collection 元素如何遍历?哪种最好?
- 遍历方式有三种:for 循环遍历,迭代器遍历,foreach 遍历。
- 哪种最好:Java Collection 提供了一个 RandomAccess 接口。如果实现类实现了这个接口,那么用 for 循环遍历效率也很高。否则用迭代器遍历和 foreach 遍历效率更高。
2.2 List 接口
List 通用的常用方法有哪些?
- 常用方法:isEmpty, indexOf, contains, iterator, clear, clone, size, toArray, hashCode。
ArrayList, Vector 常用方法有哪些?
- 常用方法:增删改查方法是 add, remove, set, get。⭐
- 增:add。
- 删:remove。
- 改:set。
- 查:get。
LinkedList 常用方法有哪些?
- 常用方法:增删改查方法是 add, offer, push, poll, pop, remove, set, get, peek。⭐
- 增:add, offer, push。
- 删:poll, pop, remoe。
- 改:set。
- 查:get, peek。
- 当然还有很多变种的,结尾加 First, Last 即可。
Stack 常用方法有哪些?
-
常用方法:增删改查方法是 push, pop, peek, search。
-
增:push。
-
删:pop。
-
改:没有(naidesu 悲)。
-
查:peek, search。
-
-
Stack 就这几种方法,没有其他 List 的公用方法。还有一个判断方法 empty。
如何实现数组和 List 的转换?
-
数组转换为 List:
-
// Collections.toArray() 用法: Integer[] array = new Integer[list.size()]; list.toArray(array); // 用法1:list.toArray(目标数组) array = list.toArray(new Integer[0]); // 用法2:a = list.toArray(new Type[0]) 利用 new Type[0] 转换 Object 类型 array = list.toArray((Integer[]) new Object(list.size)) // 用法3:a = list.toArray((Type[]) new Object(list.size())) 利用 (Type[]) 强制类型转换
-
List 转换为数组:
-
//Arrays.asList() 用法: Integer[] array = {1, 2, 3}; // 源数组必须为包装类数组 List<Integer> list = Arrays.asList(array); // 用法1:直接调用 Arrays.asList() List<Integer> list = new ArrayList<>(Arrays.asList(array)); // 用法2:利用 new Type<>() 修改 Arrays.asList 的类型
多线程情况下如何使用 ArrayList?
-
可以通过 Collections.synchronizedList 方法,将 arrayListA 转换为线程安全的 arrayListB。
-
List<String> arrayListB = Collections.synchronizedList(arrayListB);
2.3 Set 接口
Set 通用的常用方法有哪些?
- 常用方法:isEmpty, contains, iterator, clear, clone, size, hashCode。
- 特点:增删方法都是 add, remove。没有改查方法。⭐
TreeSet 常用的方法有哪些?
- 常用方法:floor, lower, ceiling, higher, first, last。
- 更小一点的:floor, lower。
- 更大一点的:ceiling, higher。
- 头尾:first, last。
hashCode 和 equals 方法有什么关系?equals 和 == 又有什么关系?
- equals 用于判断值是否相等。
- == 用于判断地址是否相等。
- hashCode。如果 equals,hashCode 一定相等。如果 hashCode 相等,不一定 equals。
2.4 Queue 接口
Queue 通用的常用方法有哪些?
- 常用方法:isEmpty, contains, iterator, clear, clone, size, hashCode。
Deque 常用的方法有哪些?
- 常用方法:增删改查方法是 add, offer, push, poll, pop, remove, set, get, peek。⭐
- 增:add, offer, push。
- 删:poll, pop, remove。
- 改:set。
- 查:get, peek。
- 当然还有很多变种的,结尾加 First, Last 即可。
poll 和 remove 有什么区别?
- 队列为空时,poll 返回 null,remove 报错。
3. Map 接口
Map 通用的方法有哪些?
-
常用方法:增删改查是 put, remove, replace, get, getOrDefault, containsKey, containsValue。
- 增:put。
- 删:remove。
- 改:replace。
- 查:get, getOrDefault, containsKey, containsValue。
- 注意:put 是增加,replace 是修改。不要看到 get 是查就认为 put 是改。改是 replace!⭐
-
其他常用方法:entrySet, keySet, values, isEmpty, contains, iterator, clear, clone, size, hashCode。
- 遍历常用方法:entrySet, KeySet, values。
参考内容
- Java 集合容器面试题(2020最新版)
entrySet, keySet, values, isEmpty, contains, iterator, clear, clone, size, hashCode。
- 遍历常用方法:entrySet, KeySet, values。
参考内容
- Java 集合容器面试题(2020最新版)
- Java Platform SE 8