算法JAVA常用库语法
导入包:import java.util.*
简单数组
1 | s.toCharArray(); // 返回char[] , 例如:[1,a,2,c] |
字符串
1 | String s="1a2c" |
集合
一、集合框架核心接口
List
List 列表(有序可重复)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32List<String> list = new ArrayList<>();
list.add("Java"); // 添加元素
list.get(0); // 按索引访问
list.remove(0); // 按索引删除【注意是索引】
// 转普通数组
String[] array = list.toArray(new String[0]);
Integer[] integerArray = list.toArray(new Integer[0]);
// 手动将int数组转换为ArrayList
ArrayList<Integer> List<Integer> list = new ArrayList<>();
for (int value : intArray) { list.add(value); }
// 使用构造函数进行浅拷贝
List<String> copiedList = new ArrayList<>(originalList);
// 使用 addAll 方法进行浅拷贝
copiedList.addAll(originalList);
// 深拷贝
List<Person> copiedList = new ArrayList<>();
for (Person person : originalList) {
copiedList.add(person.clone());
}
// 查找单个元素
int index = list.indexOf(target);//首个下标
int index = list.lastIndexOf(target);// 最后下标
List.of(x, y,z)// 生成一个list,包含[x,y,z]
// 比较
list1.equals(list2); // 比较元素和位置,但不比较地址ArrayList
1
new ArrayList<Integer>(List.of(x, y,z)) //生成一个list,包含[x,y,z],并转为arraylist
LinkedList
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// 添加元素到列表末尾
linkedList.add("Nihao");
linkedList.add("Hello");
// 添加元素到列表开头
linkedList.addFirst("Bonjour");
.addLast()
// 获取第一个和最后一个元素
String firstElement = linkedList.getFirst();
String lastElement = linkedList.getLast();
// 移除第一个和最后一个元素
String removedFirst = linkedList.removeFirst();
String removedLast = linkedList.removeLast();
Set
- Set 集合(无序唯一)
1
2
3
4Set<Integer> set = new HashSet<>();
set.add(10); // 添加元素(自动去重)
set.contains(10); // 存在性检查
set1.equals(set2); // 仅比较元素
Map
- Map 映射(键值对)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36Map<String, Integer> map = new HashMap<>();
map.put("key", 100); // 插入键值对
map.get("key"); // 按键取值
map.keySet(); // 获取所有键的Set视图
map.values(); // 获取所有值的set视图
map.containsKey(xxx) // 判断是否包含key(返回bool)
map.containsValue(xx) // 判断是否包含value(返回bool)
map.getOrDefault(key, new ArrayList<String>()) //如果key存在就用存在的,不存在就用第二号元素
map.merge(s, 2, Integer::sum); // 等于cnt[s]+=2,需要value是int类型
// `Integer::sum` 也可以使用 lambda 表达式来替代:`(a, b) -> a + b`
// 如果 remappingFunction 计算出的新值为 null,则移除该键值对。例如 `scores.merge("Bob", 0, (oldValue, newValue) -> null);`则"Bob"被移除
map.computeIfAbsent(key,k -> new ArrayList<>())//如果键已经存在,则返回对应的值;如果键不存在,则使用 mappingFunction 计算一个新的值,比如这里就是创建一个新的ArrayList
// 使用构造函数进行浅拷贝
Map<String, Integer> copiedMap = new HashMap<>(originalMap);
// 使用 putAll 方法进行浅拷贝
copiedMap.putAll(originalMap);
// 深拷贝
Map<String, Book> copiedMap = new HashMap<>();
// 注意==Map.Entry==
for (Map.Entry<String, Book> entry : originalMap.entrySet()) {
copiedMap.put(entry.getKey(), entry.getValue().clone());
}
// map转arraylist,类似于:[1,2,3,4]
ArrayList<元素类型>(map.values());
linkedHashMap.keySet().stream().findFirst().get();// 获取链表第一个
// 比较
map1.equals(map2);// 比较键值对
STD
Queue
Queue 队列
1
2
3
4Queue<String> queue = new LinkedList<>(); // 注意是LinkedList实现的
queue.offer("first")/.add("first"); // 入队
queue.poll(); // 出队
queue.peek(); // 获取第一个,但不出队PriorityQueue 队列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
priorityQueue.add(10);
priorityQueue.offer(20); // 与add方法类似
Integer head = priorityQueue.peek(); // 返回头部元素,但不移除
Integer head = priorityQueue.poll(); // 返回头部元素,并从队列中移除
boolean isEmpty = priorityQueue.isEmpty();
PriorityQueue<Integer> customPriorityQueue = new PriorityQueue<>(new Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return o2.compareTo(o1); // 降序排列
}
});// 如果不写:**默认是最小的元素在前**Deque
1
2
3
4
5
6
7
8
9
10
11
12// 可以用来模拟栈
Deque<Character> stack = new LinkedList<Character>();
stack.pop() // 弹出
stack.pull(val) // 推送
// 双端队列
Deque<Integer> q = new ArrayDeque<>(); // 双端队列
.removeLast();
.addLast();
.getFirst();
...
new Stack<>();
二、常用实现类对比
类型 | 实现类 | 数据结构 | 特性 |
---|---|---|---|
List | ArrayList | 动态数组 | 随机访问快,增删慢 |
LinkedList | 双向链表 | 增删快,随机访问慢 | |
Set | HashSet | 哈希表 | O(1)查找,无序 |
TreeSet | 红黑树 | 自动排序,O(log n)操作 | |
Map | HashMap | 哈希表 | 快速查找,允许null键值 |
LinkedHashMap | 链表+哈希表 | 保留插入顺序 | |
Queue | PriorityQueue | 堆(优先队列) | 按自然顺序或Comparator排序 |
三、关键工具类语法
Collections工具类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// 排序(需实现Comparable接口)
Collections.sort(list); // 默认由小到大
// 使用自定义比较器按字符串长度排序
Collections.sort(strings, new Comparator<String>() {
public void compare(String s1, String s2)
{
//默认是越小越前面
return Integer.compare(s1.length(), s2.length());
}
});
// 二分查找(必须先排序)
int index = Collections.binarySearch(list, "Java");
// java 的 `Arrays.binarySearch`,在数组包含[多个] target 的情况下,返回的[不一定]是第一个 ≥target 的元素下标,所以无法使用。
// 创建不可变集合(Java 9+)
List<String> immutableList = List.of("A", "B", "C");
// 反转列表
Collections.reverse(list);Arrays工具类
1
2
3
4
5
6
7
8
9
10
11
12// 数组转集合(返回固定大小列表)
List<String> list = Arrays.asList("A", "B", "C");
// 快速填充
int[] arr = new int[5];
Arrays.fill(arr, 100);
// 二分查找
int index = Arrays.binarySearch(array, 3);
// 复制数组
int[] copiedArray = Arrays.copyOf(array, 6); // 新数组长度为6
Stream
::
是方法引用(Method Reference)的语法符号
举例:类名::静态方法名 / 实例对象::实例方法名 / 类名::实例方法名
一、创建 Stream
方法 | 示例 | 说明 |
---|---|---|
List/Set.stream() |
List.of(1,2,3).stream() |
从集合创建流 |
Arrays.stream() |
Arrays.stream(new int[]{1,2,3}) |
从数组创建流 |
Stream.of() |
Stream.of("a", "b", "c") |
直接创建流 |
IntStream.range() |
IntStream.range(1,5) |
生成 1-4 的整数流 |
二、中间操作(返回新 Stream)
方法 | 示例 | 作用 |
---|---|---|
filter(Predicate) |
.filter(n -> n % 2 == 0) |
过滤偶数 |
map(Function) |
.map(s -> s.length()) |
将字符串映射为长度 |
flatMap(Function) |
.flatMap(list -> list.stream()) |
扁平化嵌套集合 |
sorted() |
.sorted(Comparator.reverseOrder()) |
倒序排序 |
distinct() |
.distinct() |
去重 |
limit(long) |
.limit(3) |
取前 3 个元素 |
peek(Consumer) |
.peek(System.out::println) |
调试查看元素 |
三、终端操作(触发计算)
方法 | 示例 | 作用 |
---|---|---|
forEach(Consumer) |
.forEach(s -> System.out.print(s)) |
遍历元素 |
collect(Collector) |
.collect(Collectors.toList()) |
转换为集合 |
toList() (Java 16+) |
.toList() |
直接转为不可变列表 |
reduce() |
.reduce(0, (a,b) -> a + b) |
求和(归约) |
count() |
.count() |
统计元素数量 |
anyMatch(Predicate) |
.anyMatch(s -> s.startsWith("A")) |
是否存在以 A 开头的元素 |
allMatch(Predicate) |
.allMatch(n -> n > 0) |
是否所有元素大于 0 |
mapToInt() |
mapToInt(Integer::intValue) |
转为整数 |
mapToInt(String::length) |
以每个流的字符串长度作为新值 | |
mapToInt(x -> x.length()) |
以每个流的字符串长度作为新值 |
四、常见组合示例
1. 过滤 + 映射
1 | List<String> names = List.of("Alice", "Bob", "Charlie"); |
2. 扁平化处理嵌套集合
1 | List<List<Integer>> nestedList = List.of(List.of(1,2), List.of(3,4)); |
3. 统计操作
1 | long count = Stream.of("apple", "banana", "orange") |
4. 归约求和
1 | int sum = IntStream.range(1, 5) // 1,2,3,4 |
输入输出
1 | Scanner scanner = new Scanner(System.in); |
板子
【二分】闭区间1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// 输出首个>=target的位置。
int left=0;
int right=nums.length-1;
while(left<=right){
int mid=left+(right-left)/2;
if(nums[mid]<target){
left=mid+1;
}else if(nums[mid]>target){
right=mid-1;
}else{
return mid;
}
}
return left;
【快排】1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35public static int[] quickSort(int[] arr, int left, int right) {
int i, j, temp, t;
if (left > right) {
return null;
}
i = left;
j = right;
// 1 2 3 4 5 6
// pr i j
//
temp = arr[left];//基准位
while (i < j) {
//先从右边将j依次往左移动
while (arr[j] >= temp && i < j) {
j--;
}
//再从左边将i依次往右移动
while (arr[i] <= temp && i < j) {
i++;
}
//满足条件则交换
if (i < j) {
t = arr[j];
arr[j] = arr[i];
arr[i] = t;
}
}
//最后将基准元素为与i和j[相等]位置的元素交换
arr[left] = arr[i];
arr[i] = temp;
quickSort(arr, left, j - 1);//递归调用左半数组
quickSort(arr, j + 1, right);//递归调用左半数组
return arr;
}
【堆排】1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47// 这段代码实现的是构建大顶堆(最大堆)
void heapify(int[] nums, int n, int i) {
int largest = i;
int left = 2 * i + 1;// 左子树
int right = 2 * i + 2;// 右子树
if (left < n && nums[left] > nums[largest]) {
largest = left;
}
if (right < n && nums[right] > nums[largest]) {
largest = right;
}
// 找到最大的
if (largest != i) {
// 交换最大值
int temp = nums[i];
nums[i] = nums[largest];
nums[largest] = temp;
// `n` 主要代表数组的长度
heapify(nums, n, largest);// 递归子树
}
}
// 查找数组中第 k 大的元素
public int findKthLargest(int[] nums, int k) {
int n = nums.length;
// 构建最大堆
// 注意这里的i的取值,从第一个非叶子节点开始取值
for (int i = n / 2 - 1; i >= 0; --i) {
heapify(nums, n, i);
}
// 提取前 k 个最大值
for (int i = n - 1; i >= n - k; --i) {
// 交换
int temp = nums[0];
nums[0] = nums[i];
nums[i] = temp;
// 第i大的排序后,只需排前i个数字,所以这里第二个参数=i
heapify(nums, i, 0);
}
return nums[n - k];
}