Java 集合的使用
本文题目难度标识:🟩简单,🟨中等,🟥困难。
集合 Collection/Map

集合增删改查速览:
接口 | Collection | List | Queue | Deque | Set |
|---|---|---|---|---|---|
| 增 | add(E e) | add(int index,E element)、addAll(c) | 抛异常:add(e)返回特殊值: offer(e) | 抛异常:addFirst(e)、addLast(e)、push(e)返回特殊值: offerFirst(e)、offerLast(e) | |
| 删 | remove(Object o) 移除指定对象clear() 清空所有内容 | 子类 ArrayList 重载了 remove 方法,使其可以通过索引删除指定位置的元素。 | 抛异常:remove()返回特殊值: poll() | 抛异常:removeFirst()、removeLast()、pop()返回特殊值: pollFirst()、pollLast() | boolean remove(obj)移除存在的元素返回 true,移除不存在的元素返回 false |
| 改 | set(int index, E element)请避免对空列表调用该函数 | ||||
| 查 | get(int index) | 抛异常:element()返回特殊值: peek() | 抛异常:getFirst()、getLast()返回特殊值: peekFirst()、peekLast() | ||
| 判断 | contains(Object o)isEmpty() | ||||
List 的灵活操作:
- 子列表截取:
list.subList(from,to)。用于获取列表的一部分视图,对视图的修改会反映到列表中。如需转换为独立新列表需重新构造:List<String> newList = new ArrayList<>(subView); - 拼接:
list.addAll(ls)
栈结构的使用:
- 队列也可用作 LIFO(后进先出)堆栈。应优先使用此接口而不是遗留
Stack类。在LinkedList的实现中:push(e)是往队首增加元素,实际调用addFirst(e)pop()是从队首删减元素,实际调用removeFirst(e)
List也可用于简单的栈。ls.add(e)方法作为入栈,ls.remove(ls.size() - 1)作为出栈。
变长数组可以使用 ArrayList 进行实现。
接口 | Map | 说明 |
|---|---|---|
| 增 | put(key,value) | |
| 删 | remove(key) 删除 key 对应的键值对clear() 清空 map | |
| 改 | put(key,newValue) | |
| 查 | get(key)getOrDefault(key,defaultValue) | |
| 判断 | containsKey(key)containsValue(value) | |
| 集合 | entrySet()keySet() | 注意,没有关于值的集合。 |
getOrDefault 的使用有时候我们会编写这样的代码:map.getOrDefault(key,func());,我们会误以为只有 map 不存在 key 时才会调用 func()。事实上,Java 在传递参数给方法前,都会计算参数的值。因此即使 key 存在,func() 还是会执行一次。
如果我们需要 map 不存在时才执行 func(),可以使用 computeIfAbsent 函数:map.computeIfAbsent(key,e->func());
或者使用三元运算符:int result = map.containsKey(key)? map.get(key) : func();
Map 的遍历
1 | // Map 遍历元组对 |
用 Map 计数
1 | Map<Character,Integer> map = new HashMap<>(); |
方法:hashmap.merge(key, value, remappingFunction)
merge()方法会先判断指定的key是否存在,如果不存在,则添加键值对到hashMap中。merge()返回值:如果key对应的value不存在,则返回该value值,如果存在,则返回通过remappingFunction重新计算后的值。- 重新映射函数可以使用 站内文章Lambda 表达式,比如:
(oldValue, newValue) -> oldValue + newValue)
1 | Map<Character,Integer> map = new HashMap<>(); |
哈希算法
Array 与 List 之间的转换
两者之间的转换除了 for 循环外,还有以下方式。
Array2List:
1 | String[] array = {"A","B","C"}; // 基本类型数组的话必须是包装类型数组 |
【强制】使用工具类 Arrays.asList() 把数组转换成集合时, 不能使用其修改集合相关的方法, 它的 add / remove / clear 方法会抛出 UnsupportedOperationException 异常。
说明: asList 的返回对象是一个 Arrays 内部类, 并没有实现集合的修改方法。 Arrays.asList 体现的是 站内文章适配器模式, 只是转换接口, 后台的数据仍是数组。
List2Array:
1 | List<String> ls = new ArrayList<String>(){{add("aa");add("bb");add("cc");}}; |
注意 String[] array = (String [])ls.toArray(); 是不对的。因为 ls.toArray() 返回的 Object[] 类不能向下转型为 String[]。有关 List 的 toArray 方法详看:站内文章这篇文章。
Set转数组也可以使用toArray(T[] array)。
【强制】 使用集合转数组的方法, 必须使用集合的 toArray(T[] array), 传入的是类型完全一致、 长度为 0 的空数组。
List 的复制
1 | // 底层源码涉及到了 Arrays.toArray() |
集合的排序
集合的排序详见:站内文章Java 中的排序
TreeSet TreeMap 的一些常用方法
以下函数在与「线段树」有关的题目的题解下见得多。可以稍微了解下,毕竟玩 API 玩得好能节省时间。
tset.floor(E e)方法返回在这个集合中小于或者等于给定元素的最大元素,如果不存在这样的元素,返回nulltset.ceiling(E e)方法返回在这个集合中大于或者等于给定元素的最小元素,如果不存在这样的元素,返回nulltset.last()tset.lower()tmap.floorEntry(E e)tmap.higherEntry(E e)tmap.firstEntry()tmap.subMap(E fromKey, E toKey):返回一个视图,其键范围从fromKey(包括)到toKey(不包括)。注意,子Map中的更改会反映在原始Map中。
相关题目: 🟨 729. 我的日程安排表 I - 力扣(LeetCode)
优先队列 PriorityQueue
优先队列使用了堆数据结构,堆的形式为数组。基本方法为 peek()、offer(e)、poll()/remove()。
remove() 的另一个重载方法 remove(obj):尝试从队列中移除指定的对象。如果对象存在于队列中,它将被移除,并返回 true;否则返回 false。时间复杂度为 。
因为 PriorityQueue 中插入删除的数据是泛型类,可以是基本类型对应的包装类,也可以是自定义类,在向上调整和向下调整的过程中,需要不断地比较,如果数据没有指定比较规则,或者为 null 时,程序就会抛出异常。
1 | Queue<Integer> priorityQueue1 = new PriorityQueue<>(); // 默认数组容量 11 |
Java 集合中的 PriorityQueue 底层的堆默认是小根堆,如果要设置大根堆,就必须传入比较器, 并重写 compare 方法。





