面试JAVA集合常用方法总结
ArrayList
基于动态数组实现,支持随机索引访问,访问索引的时间复杂度O(1),非线程安全
方法 | 用处 |
---|---|
size() | 返回列表中的元素数量。 |
add(E e) | 将指定元素添加到列表末尾。 |
add(int index, E e) | 将指定元素插入到指定位置。 |
get(int index) | 返回指定索引处的元素。 |
remove(int index) | 删除指定索引处的元素。 |
remove(Object o) | 删除第一个匹配的元素。 |
set(int index, E e) | 将指定索引处的元素替换为新值。 |
clear() | 清空列表中的所有元素。 |
toArray() | 将列表转换为数组。 |
contains(Object o) | 判断列表是否包含指定元素。 |
ArrayList的排序
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class LCR074 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(3);
list.add(1);
list.add(2);
// 默认升序排序
Collections.sort(list);
System.out.println(list); // 输出:[1, 2, 3]
// 自定义降序排序
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1); // 降序
}
});
System.out.println(list); // 输出:[3, 2, 1]
}
}
LinkedList
基于双向链表实现,不支持随机索引访问,需要O(n)的时间复杂度遍历查找。但可以向头和尾以O(1)的时间复杂度插值。
方法 | 用法 |
---|---|
size() | 返回列表中的元素数量。 |
isEmpty() | 判断列表是否为空 |
clear() | 清空列表中的所有元素 |
add(E e) | 将指定元素添加到列表末尾。 |
addFirst(E e) | 将指定元素添加到列表头部。 |
addLast(E e) | 将指定元素添加到列表尾部。 |
add(int index, E e) | 将指定元素插入到指定位置。 |
get(int index) | 返回指定索引处的元素。 |
first() | 返回列表的第一个元素。 |
last() | 返回列表的最后一个元素。 |
remove(int index) | 删除指定索引处的元素。 |
removeFirst() | 删除列表的第一个元素。 |
removeLast() | 删除列表的最后一个元素。 |
remove(Object o) | 删除第一个匹配的元素。 |
set(int index, E e) | 将指定索引处的元素替换为新值。 |
toArray() | 将列表转换为数组。 |
contains(Object o) | 判断列表是否包含指定元素。 |
HashMap
JDK1.7之前,HashMap是基于数组和链表实现的,JDK1.8之后,如果链表长度超过8,链表就转为红黑树。非线程安全
方法 | 用法 |
---|---|
put(K key, V value) | 将键值对添加到 HashMap 中。如果键已存在,则更新对应的值。 |
putIfAbsent(K key, V value) | 如果键不存在,则添加键值对;如果键已存在,则不更新。 |
get(Object key) | 根据键获取对应的值。如果键不存在,返回 null。 |
getOrDefault(Object key, V defaultValue) | 根据键获取对应的值。如果键不存在,返回默认值。 |
remove(Object key) | 根据键删除对应的键值对。 |
remove(Object key, Object value) | 只有当键和值都匹配时,才删除键值对。 |
containsKey(Object key) | 检查是否包含指定的键。 |
containsValue(Object value) | 检查是否包含指定的值。 |
size() | 返回 HashMap 中键值对的数量。 |
isEmpty() | 检查 HashMap 是否为空。 |
replace(K key, V value) | 替换指定键的值(键必须存在)。 |
replace(K key, V oldValue, V newValue) | 只有当键和旧值都匹配时,才替换为新值 |
Hashmap的遍历:
import java.util.HashMap;
public class LCR074 {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<>();
map.put("nihao",1);
//遍历键值对
for (HashMap.Entry<String, Integer> entry : map.entrySet()) {
System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}
//遍历键
for (String key : map.keySet()) {
System.out.println("Key: " + key);
}
//遍历值
for (Integer value : map.values()) {
System.out.println("Value: " + value);
}
}
}
Queue
队列是一种先进先出(FIFO)的数据结构,支持在队尾添加元素,在队头移除元素。在 Java 中,Queue 是一个接口,而 LinkedList 是 Queue 接口的一个实现类。
方法 | 用法 |
---|---|
add(E e) | 将一个元素添加到队列末尾。如果队列已满,抛出 IllegalStateException。 |
offer(E e) | 将一个元素添加到队列末尾。如果队列已满,返回 false,而不是抛出异常。 |
remove() | 移除并返回队列头部的元素。如果队列为空,抛出 NoSuchElementException。 |
poll() | 移除并返回队列头部的元素。如果队列为空,返回 null,而不是抛出异常。 |
element() | 返回队列头部的元素,但不移除它。如果队列为空,抛出 NoSuchElementException。 |
peek() | 返回队列头部的元素,但不移除它。如果队列为空,返回 null,而不是抛出异常。 |
size() | 返回队列中的元素数量。 |
clear() | 清空队列中的所有元素。 |
toArray() | 将队列转换为数组。 |
contains(Object o) | 判断队列是否包含指定元素。 |
常用算法:bfs
import java.util.LinkedList;
import java.util.Queue;
public class BFSExample {
public static void main(String[] args) {
Queue<Integer> queue = new LinkedList<>();
queue.add(1);
while (!queue.isEmpty()) {
int current = queue.poll();
System.out.println("Visited: " + current);
// 添加邻接节点到队列
queue.add(current + 1);
queue.add(current + 2);
}
}
}
Stack
Stack 是 Java 中的一个类,继承自 Vector,用于实现后进先出(LIFO,Last In First Out)的栈数据结构。
方法 | 用法 |
---|---|
push(E item) | 将一个元素压入栈顶 |
pop() | 移除并返回栈顶元素。 |
peek() | 返回栈顶元素,但不移除它。 |
empty() | 判断栈是否为空。 |
常用算法:括号匹配、单调栈
括号匹配:使用栈检查括号是否成对匹配。
import java.util.Stack;
public class ParenthesesMatch {
public static boolean isValid(String s) {
Stack<Character> stack = new Stack<>(); // 使用栈来存储左括号
for (char c : s.toCharArray()) { // 遍历字符串中的每个字符
// 如果是左括号,压入栈中
if (c == '(' || c == '{' || c == '[') stack.push(c);
// 如果是右括号,检查栈顶是否匹配
else if (stack.isEmpty() || // 栈为空,说明没有匹配的左括号
(c == ')' && stack.pop() != '(') || // 弹出栈顶并检查是否匹配
(c == '}' && stack.pop() != '{') ||
(c == ']' && stack.pop() != '[')) return false; // 不匹配则返回 false
}
return stack.isEmpty(); // 如果栈为空,说明所有括号都匹配
}
public static void main(String[] args) {
System.out.println(isValid("()[]{}")); // true
System.out.println(isValid("([)]")); // false
}
}
单调栈:用于解决“下一个更大元素”类问题,栈中保持单调递减。
import java.util.Stack;
public class MonotonicStack {
public static int[] nextGreaterElement(int[] nums) {
int[] result = new int[nums.length]; // 存储结果的数组
Stack<Integer> stack = new Stack<>(); // 单调栈,栈底到栈顶单调递减
for (int i = nums.length - 1; i >= 0; i--) { // 从后往前遍历数组
// 如果栈顶元素小于当前元素,弹出栈顶(维护单调性)
while (!stack.isEmpty() && stack.peek() <= nums[i]) stack.pop();
// 如果栈为空,说明没有更大的元素;否则栈顶就是下一个更大元素
result[i] = stack.isEmpty() ? -1 : stack.peek();
// 将当前元素压入栈中
stack.push(nums[i]);
}
return result;
}
public static void main(String[] args) {
int[] nums = {2, 1, 2, 4, 3};
int[] result = nextGreaterElement(nums);
for (int num : result) System.out.print(num + " "); // 输出: 4 2 4 -1 -1
}
}
PriorityQueue
优先队列,可以理解成有序的队列。
方法 | 用处 |
---|---|
add(E e) | 将元素插入优先队列。如果队列已满,抛出异常。 |
offer(E e) | 将元素插入优先队列。如果队列已满,返回 false。 |
remove() | 移除并返回队列头部元素(优先级最高的元素)。如果队列为空,抛出异常。 |
poll() | 移除并返回队列头部元素(优先级最高的元素)。如果队列为空,返回 null。 |
element() | 返回队列头部元素(不移除)。如果队列为空,抛出异常。 |
peek() | 返回队列头部元素(不移除)。如果队列为空,返回 null。 |
size() | 返回队列中的元素数量。 |
isEmpty() | 检查队列是否为空。 |
clear() | 清空队列中的所有元素。 |
contains(Object o) | 检查队列中是否包含指定元素。 |
toArray() | 将队列转换为数组。 |
iterator() | 返回队列的迭代器。 |
comparator() | 返回队列的比较器(如果未指定比较器,返回 null)。 |
(1) 最小堆优先队列,优先返回队列中最小值
import java.util.PriorityQueue;
public class PriorityQueueExample {
public static void main(String[] args) {
// 创建一个最小堆优先队列
PriorityQueue<Integer> minHeap = new PriorityQueue<>();
// 添加元素
minHeap.add(10);
minHeap.add(5);
minHeap.add(20);
minHeap.add(15);
// 输出队列中的元素(按优先级顺序)
while (!minHeap.isEmpty()) {
System.out.println(minHeap.poll()); // 输出: 5, 10, 15, 20
}
}
}
(2) 最大堆优先队列,优先返回队列中最大值
import java.util.PriorityQueue;
public class PriorityQueueExample {
public static void main(String[] args) {
// 创建一个最大堆优先队列
PriorityQueue<Integer> maxHeap = new PriorityQueue<>((a, b) -> b - a);
// 添加元素
maxHeap.add(10);
maxHeap.add(5);
maxHeap.add(20);
maxHeap.add(15);
// 输出队列中的元素(按优先级顺序)
while (!maxHeap.isEmpty()) {
System.out.println(maxHeap.poll()); // 输出: 20, 15, 10, 5
}
}
}
(3) 自定义对象的优先队列,自己定义排序方式
import java.util.PriorityQueue;
public class PriorityQueue2DArray {
public static void main(String[] args) {
int[][] array = {
{3, 5},
{1, 2},
{4, 1},
{2, 8},
{5, 7}
};
// 创建一个优先队列,按第 0 列排序(最小堆)
PriorityQueue<int[]> minHeap = new PriorityQueue<>((a, b) -> a[0] - b[0]);
// 将二维数组的每一行加入优先队列
for (int[] row : array) {
minHeap.offer(row);
}
// 按优先级顺序输出
while (!minHeap.isEmpty()) {
int[] row = minHeap.poll();
System.out.println("[" + row[0] + ", " + row[1] + "]");
}
}
}
常用算法:dijkstra
import java.util.*;
public class Dijkstra {
// 定义图的边
static class Edge {
int target; // 目标节点
int weight; // 边的权重
public Edge(int target, int weight) {
this.target = target;
this.weight = weight;
}
}
// Dijkstra 算法实现
public static int[] dijkstra(List<List<Edge>> graph, int start) {
int n = graph.size(); // 图中节点的数量
int[] dist = new int[n]; // 存储从起点到每个节点的最短距离
Arrays.fill(dist, Integer.MAX_VALUE); // 初始化为无穷大
dist[start] = 0; // 起点到自身的距离为 0
// 优先队列(最小堆),按距离排序
PriorityQueue<int[]> pq = new PriorityQueue<>(Comparator.comparingInt(a -> a[1]));
pq.offer(new int[]{start, 0}); // 将起点加入队列
while (!pq.isEmpty()) {
int[] current = pq.poll(); // 取出当前距离最小的节点
int node = current[0];
int distance = current[1];
// 如果当前节点的距离已经大于记录的最短距离,跳过
if (distance > dist[node]) continue;
// 遍历当前节点的所有邻居
for (Edge edge : graph.get(node)) {
int neighbor = edge.target;
int newDist = dist[node] + edge.weight;
// 如果找到更短的路径,更新距离并加入队列
if (newDist < dist[neighbor]) {
dist[neighbor] = newDist;
pq.offer(new int[]{neighbor, newDist});
}
}
}
return dist; // 返回起点到所有节点的最短距离
}
public static void main(String[] args) {
// 示例:图的邻接表表示
int n = 5; // 节点数量
List<List<Edge>> graph = new ArrayList<>();
for (int i = 0; i < n; i++) {
graph.add(new ArrayList<>());
}
// 添加边
graph.get(0).add(new Edge(1, 4)); // 0 -> 1,权重 4
graph.get(0).add(new Edge(2, 1)); // 0 -> 2,权重 1
graph.get(1).add(new Edge(3, 1)); // 1 -> 3,权重 1
graph.get(2).add(new Edge(1, 2)); // 2 -> 1,权重 2
graph.get(2).add(new Edge(3, 5)); // 2 -> 3,权重 5
graph.get(3).add(new Edge(4, 3)); // 3 -> 4,权重 3
int start = 0; // 起点
int[] dist = dijkstra(graph, start);
// 输出结果
System.out.println("从节点 " + start + " 到其他节点的最短距离:");
for (int i = 0; i < n; i++) {
System.out.println("到节点 " + i + " 的距离: " + dist[i]);
}
}
}