Java算法

Java 中 Deque 的详解(模拟栈和队列)

1. 什么是 Deque

DequeDouble Ended Queue(双端队列) 的缩写,是 Java 集合框架中的接口之一。特点:

  • 可以在 队头(front)和队尾(rear) 同时插入和删除元素。
  • 可以用作:
    • 队列(FIFO):先进先出
    • 栈(LIFO):后进先出

常用实现类:

  • ArrayDeque(数组实现,速度快,不允许 null
  • LinkedList(链表实现,允许 null

2. 核心方法

2.1 插入元素

方法 功能 异常/返回值
addFirst(E e) 队头插入元素 队列满时抛异常
addLast(E e) 队尾插入元素 队列满时抛异常
offerFirst(E e) 队头插入元素 队列满返回 false
offerLast(E e) 队尾插入元素 队列满返回 false

2.2 删除元素

方法 功能 异常/返回值
removeFirst() 删除并返回队头元素 空队列抛异常
removeLast() 删除并返回队尾元素 空队列抛异常
pollFirst() 删除并返回队头元素 空队列返回 null
pollLast() 删除并返回队尾元素 空队列返回 null

2.3 查看元素(不删除)

方法 功能 异常/返回值
getFirst() 获取队头元素 空队列抛异常
getLast() 获取队尾元素 空队列抛异常
peekFirst() 获取队头元素 空队列返回 null
peekLast() 获取队尾元素 空队列返回 null

2.4 栈操作方法(LIFO)

方法 功能
push(E e) 将元素压入栈顶(相当于 addFirst
pop() 弹出栈顶元素(相当于 removeFirst
peek() 查看栈顶元素(相当于 peekFirst

2.5获取队列长度

deque.size();

3. 常见实现类

3.1 ArrayDeque

Deque<Integer> deque = new ArrayDeque<>();

特点:

  • 内部基于数组实现
  • 不允许 null
  • LinkedList 更快(无额外链表开销)
  • 动态扩容

3.2 LinkedList

Deque<String> deque = new LinkedList<>();

特点:

  • 双向链表实现
  • 允许 null
  • 支持队列和栈操作

4. 使用示例

4.1 双端队列操作

import java.util.ArrayDeque;
import java.util.Deque;

public class DequeExample {
    public static void main(String[] args) {
        Deque<Integer> deque = new ArrayDeque<>();

        // 插入元素
        deque.addFirst(1);   // 1
        deque.addLast(2);    // 1 2
        deque.offerFirst(0); // 0 1 2
        deque.offerLast(3);  // 0 1 2 3

        System.out.println("Deque: " + deque);

        // 删除元素
        deque.removeFirst(); // 删除0
        deque.pollLast();    // 删除3
        System.out.println("After removing: " + deque);

        // 查看元素
        System.out.println("First: " + deque.getFirst()); // 1
        System.out.println("Last: " + deque.getLast());   // 2
    }
}

输出:

Deque: [0, 1, 2, 3]
After removing: [1, 2]
First: 1
Last: 2

4.2 当作栈使用

Deque<String> stack = new ArrayDeque<>();

stack.push("A");
stack.push("B");
stack.push("C");

while (!stack.isEmpty()) {
    System.out.println(stack.pop());
}

输出:

C
B
A

4.3 当作队列使用

Deque<String> queue = new ArrayDeque<>();

queue.offer("A");
queue.offer("B");
queue.offer("C");

while (!queue.isEmpty()) {
    System.out.println(queue.poll());
}

输出:

A
B
C

5. 总结

  • Deque 是双端队列接口,支持从两端插入/删除。
  • 可以用作 队列(FIFO)栈(LIFO)
  • 两大常用实现类:
    • ArrayDeque:推荐,速度快,不允许 null
    • LinkedList:灵活,允许 null
  • 方法体系:
    • 插入:addFirst/addLastofferFirst/offerLast
    • 删除:removeFirst/removeLastpollFirst/pollLast
    • 查看:getFirst/getLastpeekFirst/peekLast
    • 栈操作:push/pop/peek

Queue (单向队列) 常用方法总结

在 Java 中,Queue 是一个遵循 FIFO (先进先出) 原则的接口。为了处理可能出现的边界情况(比如试图从空队列拿东西,或者往满队列塞东西),Java 为单向队列提供了两套核心方法。

它们的核心区别在于:当操作失败时,一套会直接抛出异常导致程序崩溃,而另一套会温柔地返回一个特殊值(falsenull)。

初始化:

Queue<Integer> queue = new LinkedList<>();

1. 核心方法对比速查表

在日常开发和算法题(如 BFS)中,强烈建议优先使用右侧“返回特殊值”的方法,以避免不必要的异常处理。

操作类型 抛出异常 (操作失败时) 返回特殊值 (操作失败时) 操作说明
入队 (队尾添加) add(e) offer(e) 将指定的元素插入队列尾部。
出队 (队头移除) remove() poll() 移除并返回队列头部的第一个元素。
查看 (仅看队头) element() peek() 获取队列头部的第一个元素,但不移除它。

2. 核心方法详解

🔵 推荐组:安全方法 (不抛异常)

这组方法是你在写算法题(特别是广度优先搜索 BFS)时的绝对主力。

  • offer(E e)
    • 作用: 试图将元素 e 加入队尾。
    • 返回值: 成功返回 true;如果队列有容量限制且已满,则返回 false
  • poll()
    • 作用: 弹出并返回队头的元素。
    • 返回值: 成功返回该元素;如果队列是空的,则安全地返回 null
  • peek()
    • 作用: 偷看一眼队头的元素,但不会把它从队列中拿走。
    • 返回值: 返回队头元素;如果队列为空,返回 null

🔴 严厉组:抛出异常的方法

这组方法通常用于你“百分之百确信队列不会为空/不会满”,或者你希望通过抛出异常来中断程序的场景。

  • add(E e)
    • 如果超出队列容量限制,会直接抛出 IllegalStateException 异常。
  • remove()
    • 如果队列已经是空的,再去执行 remove(),会抛出 NoSuchElementException 异常。
  • element()
    • 如果队列为空,强行查看队头,同样会抛出 NoSuchElementException 异常。

3. 继承自 Collection 接口的常用辅助方法

既然 Queue 继承了 Collection 接口,它自然也就拥有了一些非常实用的集合通用方法:

  • isEmpty()
    • 返回值: boolean。如果队列中没有任何元素,返回 true
    • 高频场景: 作为 BFS 的核心循环条件,例如 while (!queue.isEmpty()) { ... }
  • size()
    • 返回值: int。返回当前队列中包含的元素个数。
    • 高频场景: 在多源 BFS 或按层遍历时,用来锁定当前层级的元素数量,例如 int size = queue.size();
  • clear()
    • 作用: 一键清空队列中的所有元素。
  • contains(Object o)
    • 返回值: boolean。判断队列内部是否包含某个特定的对象。时间复杂度通常是 O(N),因为需要遍历查找。

Java BigInteger 使用笔记

1. 导入包

import java.math.BigInteger;

2. 创建 BigInteger 对象

2.1 常用构造方法

// 从字符串创建
BigInteger num1 = new BigInteger("12345678901234567890");

// 从 long 转换
BigInteger num2 = BigInteger.valueOf(100L);

// 常用常量
BigInteger.ZERO    // 0
BigInteger.ONE     // 1
BigInteger.TEN     // 10

3. 基本运算

3.1 算术运算

BigInteger a = new BigInteger("100");
BigInteger b = new BigInteger("3");

a.add(b)          // 加法:103
a.subtract(b)     // 减法:97
a.multiply(b)     // 乘法:300
a.divide(b)       // 除法:33
a.remainder(b)    // 取余:1

// 同时求商和余数
BigInteger[] result = a.divideAndRemainder(b);
result[0]  // 商:33
result[1]  // 余数:1

// 幂运算
BigInteger.valueOf(2).pow(10)  // 1024

// 绝对值
a.abs()

// 相反数
a.negate()

3.2 比较运算

BigInteger a = new BigInteger("100");
BigInteger b = new BigInteger("200");

a.compareTo(b)    // a < b 返回 -1
                  // a == b 返回 0
                  // a > b 返回 1

a.equals(b)       // 是否相等
a.equals(BigInteger.ZERO)  // 是否为零

3.3 位运算

BigInteger a = new BigInteger("12");  // 1100

a.and(BigInteger.valueOf(10))   // 与:1000 (8)
a.or(BigInteger.valueOf(3))     // 或:1111 (15)
a.xor(BigInteger.valueOf(5))    // 异或:1001 (9)
a.not()                         // 非:-13
a.shiftLeft(2)                  // 左移:48 (110000)
a.shiftRight(1)                 // 右移:6 (110)

3.4 模运算(常用)

BigInteger base = new BigInteger("123");
BigInteger mod = BigInteger.valueOf(26);

// 模加
base.add(BigInteger.valueOf(5)).mod(mod)

// 模幂:计算 (base^exponent) mod modulus
base.modPow(exponent, modulus)

// 模逆
base.modInverse(modulus)

// 取模(结果非负)
base.mod(mod)

// 取余(结果可正可负)
base.remainder(mod)

4. 类型转换

4.1 转换为基本类型

BigInteger big = new BigInteger("12345");

big.intValue()        // 转换为 int(可能溢出)
big.intValueExact()   // 转换为 int(溢出抛异常,推荐)
big.longValue()       // 转换为 long
big.longValueExact()  // 转换为 long(溢出抛异常)
big.doubleValue()     // 转换为 double
big.floatValue()      // 转换为 float

4.2 转换为字符串

BigInteger big = new BigInteger("255");

big.toString()        // "255"
big.toString(2)       // 二进制:"11111111"
big.toString(16)      // 十六进制:"ff"

5. int[] 与 BigInteger[] 转换

5.1 int[] → BigInteger[]

int[] shifts = {1, 2, 3};
BigInteger[] bigints = new BigInteger[shifts.length];

// 方法1:普通循环
for (int i = 0; i < shifts.length; i++) {
    bigints[i] = BigInteger.valueOf(shifts[i]);
}

// 方法2:Stream(Java 8+)
BigInteger[] bigints = Arrays.stream(shifts)
    .mapToObj(BigInteger::valueOf)
    .toArray(BigInteger[]::new);

5.2 BigInteger[] → int[]

BigInteger[] bigints = {...};
int[] ints = new int[bigints.length];

for (int i = 0; i < bigints.length; i++) {
    ints[i] = bigints[i].intValueExact();  // 安全转换
}

6. 常见应用场景

6.1 计算阶乘

public static BigInteger factorial(int n) {
    BigInteger result = BigInteger.ONE;
    for (int i = 2; i <= n; i++) {
        result = result.multiply(BigInteger.valueOf(i));
    }
    return result;
}

6.2 字母移位(取模26)

public char shift(char word, BigInteger length) {
    // 获取实际移位量(取模26)
    int shift = length.mod(BigInteger.valueOf(26)).intValue();
    
    if (word >= 'a' && word <= 'z') {
        return (char)('a' + (word - 'a' + shift) % 26);
    }
    return word;
}

6.3 后缀和计算

int[] shifts = {3, 5, 2, 7};
BigInteger[] suffixSum = new BigInteger[shifts.length];
BigInteger total = BigInteger.ZERO;

for (int i = shifts.length - 1; i >= 0; i--) {
    total = total.add(BigInteger.valueOf(shifts[i]));
    suffixSum[i] = total;
}

7. 注意事项

7.1 不可变性

// ❌ 错误:BigInteger 是不可变的
BigInteger num = new BigInteger("10");
num.add(new BigInteger("5"));  // 结果被丢弃

// ✅ 正确:需要重新赋值
num = num.add(new BigInteger("5"));

7.2 不能使用运算符

// ❌ 错误
// BigInteger sum = a + b;

// ✅ 正确
BigInteger sum = a.add(b);

7.3 溢出检查

BigInteger big = new BigInteger("2147483648");  // 大于 int 最大值

// ❌ 静默溢出
int wrong = big.intValue();  // -2147483648

// ✅ 抛出异常
int correct = big.intValueExact();  // ArithmeticException

7.4 性能考虑

  • 小数字使用基本类型(int、long)
  • 只有超出 long 范围(> 2^63-1)时才使用 BigInteger
  • BigInteger 运算比基本类型慢得多

8. 错误解决

常见错误:cannot find symbol

// 错误:缺少导入
public class Solution {
    BigInteger num;  // ❌ 找不到符号
}

// 正确:导入 BigInteger
import java.math.BigInteger;

public class Solution {
    BigInteger num;  // ✅ 正常
}

9. 快速参考表

操作 代码示例
创建 BigInteger.valueOf(100)
加法 a.add(b)
减法 a.subtract(b)
乘法 a.multiply(b)
除法 a.divide(b)
取余 a.remainder(b)
取模 a.mod(b)
比较 a.compareTo(b)
转int a.intValueExact()
转String a.toString()
幂运算 a.pow(n)
模幂 a.modPow(exp, mod)

Collections 算法方法快速参考表

方法 用途 时间复杂度
sort(list) 升序排序 O(n log n)
sort(list, comparator) 自定义排序 O(n log n)
reverse(list) 反转顺序 O(n)
shuffle(list) 随机打乱 O(n)
shuffle(list, random) 指定随机源打乱 O(n)
rotate(list, distance) 旋转元素(右移为正) O(n)
swap(list, i, j) 交换指定位置元素 O(1)
fill(list, obj) 全部填充为指定元素 O(n)
copy(dest, src) 复制源列表到目标列表 O(n)
replaceAll(list, oldVal, newVal) 替换所有旧值为新值 O(n)
binarySearch(list, key) 二分查找(必须已排序) O(log n)
binarySearch(list, key, comparator) 自定义比较器二分查找 O(log n)
max(list) 返回最大值 O(n)
max(list, comparator) 自定义比较器返回最大值 O(n)
min(list) 返回最小值 O(n)
min(list, comparator) 自定义比较器返回最小值 O(n)
frequency(list, obj) 返回元素出现次数 O(n)
disjoint(c1, c2) 判断两集合是否无交集 O(n)
indexOfSubList(source, target) 返回子列表首次出现位置 O(n²)
lastIndexOfSubList(source, target) 返回子列表最后出现位置 O(n²)
emptyList() 返回空List(不可变) O(1)
emptySet() 返回空Set(不可变) O(1)
emptyMap() 返回空Map(不可变) O(1)
singletonList(obj) 返回单元素List(不可变) O(1)
singletonSet(obj) 返回单元素Set(不可变) O(1)
singletonMap(k, v) 返回单元素Map(不可变) O(1)
unmodifiableList(list) 返回只读List视图 O(1)
unmodifiableSet(set) 返回只读Set视图 O(1)
unmodifiableMap(map) 返回只读Map视图 O(1)
synchronizedList(list) 返回线程安全List O(1)
synchronizedSet(set) 返回线程安全Set O(1)
synchronizedMap(map) 返回线程安全Map O(1)
checkedList(list, type) 返回类型安全List O(1)
checkedSet(set, type) 返回类型安全Set O(1)
checkedMap(map, keyType, valType) 返回类型安全Map O(1)
addAll(collection, elements...) 批量添加元素 O(n)
enumeration(collection) 返回旧式Enumeration O(1)
list(enumeration) 将Enumeration转换为List O(n)

常用组合示例

需求 代码组合
降序排序 Collections.sort(list, Collections.reverseOrder())
获取第二大元素 Collections.sort(list); return list.get(list.size()-2)
检查列表是否已排序 Collections.sort(sortedCopy); return list.equals(sortedCopy)
循环移动k位 Collections.rotate(list, k % list.size())
安全迭代同步集合 synchronized (syncList) { for (item : syncList) {...} }
复制并不可变 Collections.unmodifiableList(new ArrayList<>(source))
去重并保持顺序 new LinkedHashSet<>(list)
列表转数组 list.toArray(new Integer[0])

LinkList(链表)常用方法总结

功能 方法 示例 说明
创建链表 new LinkedList<>() LinkedList<Integer> list = new LinkedList<>(); 创建双向链表
尾部添加 add(E e) list.add(10); 默认尾插
指定位置插入 add(int index, E e) list.add(1, 20); 在指定位置插入
头部添加 addFirst(E e) list.addFirst(5); 头插
尾部添加 addLast(E e) list.addLast(30); 尾插
删除指定下标 remove(int index) list.remove(1); 删除对应位置
删除指定元素 remove(Object o) list.remove(Integer.valueOf(10)); 删除第一个匹配元素
删除头节点 removeFirst() list.removeFirst(); 删除第一个元素
删除尾节点 removeLast() list.removeLast(); 删除最后一个元素
获取指定元素 get(int index) list.get(0); 获取指定位置元素
获取头节点 getFirst() list.getFirst(); 获取第一个元素
获取尾节点 getLast() list.getLast(); 获取最后一个元素
修改元素 set(int index, E e) list.set(0, 100); 修改指定位置元素
获取长度 size() list.size(); 返回元素个数
判空 isEmpty() list.isEmpty(); 是否为空
清空链表 clear() list.clear(); 删除所有元素
是否包含元素 contains(Object o) list.contains(10); 判断元素是否存在
查找元素位置 indexOf(Object o) list.indexOf(10); 返回首次出现下标
查找最后位置 lastIndexOf(Object o) list.lastIndexOf(10); 返回最后出现下标
遍历(for-each) for (E e : list) for(int x : list){} 推荐遍历方式
迭代器遍历 iterator() Iterator<Integer> it = list.iterator(); 适合边遍历边删除
入队 offer(E e) list.offer(10); 队列尾部添加
出队 poll() list.poll(); 弹出队头
查看队头 peek() list.peek(); 查看队头不删除
入栈 push(E e) list.push(10); 栈顶压入
出栈 pop() list.pop(); 栈顶弹出
查看栈顶 peek() list.peek(); 查看栈顶
双端队列头插 offerFirst(E e) list.offerFirst(1); 双端队列操作
双端队列尾插 offerLast(E e) list.offerLast(2); 双端队列操作
双端队列头删 pollFirst() list.pollFirst(); 删除队头
双端队列尾删 pollLast() list.pollLast(); 删除队尾

常见快速添加元素的方法

Deque<int[]> queue = new ArrayDeque<>();
queue.offer(new int[]{i, j})

String字符串操作

1.访问Sting中的某个字符

String.charAt(index)

2.修改Sting中的某个字符

String不可变,所有修改操作都会创建新字符串对象

public class ModifyString {
    public static void main(String[] args) {
        String str = "Java Programming";
        
        // 方法1:char数组
        char[] chars = str.toCharArray();
        chars[5] = 'P';
        System.out.println(new String(chars)); // Java Programming
        
        // 方法2:StringBuilder
        StringBuilder sb = new StringBuilder(str);
        sb.setCharAt(5, 'p');
        System.out.println(sb.toString()); // Java programming
    }
}

正则表达式re

Java 正则表达式常用方法总结

Java 正则主要使用:

import java.util.regex.*;

核心类:

作用
Pattern 编译正则表达式
Matcher 匹配器
String 自带很多正则方法

1. String 里的正则方法(最常用)

方法 示例 说明
matches(regex) "123".matches("\\d+") 整体匹配
split(regex) "a,b,c".split(",") 按正则切割
replaceAll(regex, str) "a1b2".replaceAll("\\d","*") 替换所有
replaceFirst(regex, str) "a1b2".replaceFirst("\\d","*") 替换第一个

2. Pattern 类方法

编译正则

Pattern p = Pattern.compile("\\d+");

常用方法表

方法 示例 说明
compile(regex) Pattern.compile("\\d+") 编译正则
matcher(str) p.matcher("123") 创建匹配器
matches(regex, str) Pattern.matches("\\d+","123") 静态整体匹配

3. Matcher 类方法(核心)

创建 Matcher

Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("abc123xyz");

常用方法总表

方法 说明
find() 查找下一个匹配
matches() 整体是否匹配
lookingAt() 是否从开头匹配
group() 获取匹配内容
group(int) 获取分组
start() 匹配开始位置
end() 匹配结束位置
replaceAll() 替换所有
replaceFirst() 替换第一个

4. find() 最重要

查找所有数字

Pattern p = Pattern.compile("\\d+");
Matcher m = p.matcher("a12b345c");

while (m.find()) {
    System.out.println(m.group());
}

输出:

12
345

5. matches() 和 find() 区别(高频面试)

matches()

要求:

整个字符串完全匹配

"123".matches("\\d+"); // true
"abc123".matches("\\d+"); // false

find()

只要找到一部分匹配即可

Matcher m = Pattern.compile("\\d+")
                   .matcher("abc123");

m.find(); // true

6. 分组 group()

捕获分组

Pattern p = Pattern.compile("(\\d+)-(\\d+)");
Matcher m = p.matcher("123-456");

if (m.find()) {
    System.out.println(m.group(0));
    System.out.println(m.group(1));
    System.out.println(m.group(2));
}

输出:

123-456
123
456

分组说明

写法 含义
group(0) 整个匹配
group(1) 第1组
group(2) 第2组

7. split()

多字符切割

String[] arr = "a,b;c".split("[,;]");

结果:

[a, b, c]

8. replaceAll()

替换数字

String s = "a1b2c3";

System.out.println(
    s.replaceAll("\\d", "*")
);

输出:

a*b*c*

9. 常用正则速查

正则 含义
. 任意字符
\\d 数字
\\D 非数字
\\w 字母数字下划线
\\W 非单词字符
\\s 空白字符
\\S 非空白
[abc] abc之一
[^abc] 非abc
[a-z] 小写字母
+ 1次以上
* 0次以上
? 0或1次
{n} n次
{m,n} m~n次
^ 开头
$ 结尾
() 分组
|

10. Java 正则转义(超级重要)

Java 字符串里:

"\d"

是错误的。

因为:

\ 会先被 Java 字符串转义。

所以正则里的:

\d

必须写:

"\\d"

11. 实战例子

提取所有数字

String s = "abc123def45";

Matcher m = Pattern.compile("\\d+")
                   .matcher(s);

while (m.find()) {
    System.out.println(m.group());
}

校验邮箱

String email = "test@qq.com";

boolean ok = email.matches(
    "\\w+@\\w+\\.\\w+"
);

去除所有空格

s.replaceAll("\\s+", "");

12. 刷题里最常用的

场景 方法
判断格式 matches()
提取内容 find()
替换字符 replaceAll()
切割字符串 split()
捕获分组 group()

13. 一个现实建议

很多新手:

一上来就用正则解决所有字符串题。

这是错误路线。

因为正则:

  • 可读性差
  • 调试困难
  • 性能不一定好

刷题里更合理的是:

  • 简单字符串题 → 双指针
  • 固定格式 → split
  • 真正复杂匹配 → regex

算法

图论

环的检测

public boolean hasCycle(int[][] graph) {
    int n = graph.length;
    int[] state = new int[n];

    for (int i = 0; i < n; i++) {
        if (dfs(graph, i, state)) {
            return true; // 有环
        }
    }
    return false;
}

private boolean dfs(int[][] graph, int node, int[] state) {
    if (state[node] == 1) return true;  // 发现环
    if (state[node] == 2) return false; // 已确认安全

    state[node] = 1; // 标记为“访问中”

    for (int next : graph[node]) {
        if (dfs(graph, next, state)) {
            return true;
        }
    }

    state[node] = 2; // 标记为安全
    return false;
}

判断逻辑(重点!)

如果你访问到一个 state == 1 的节点 → 有环

👉 因为说明你“绕回来了”(回到了当前路径上的点)

上下左右移动

public static final int[][] DIRS = {  
        {0,-1},{0,1},{-1,0},{1,0}  
};

// ......

// BFS  
while (!queue.isEmpty()) {  
  
    int[] cur = queue.poll();  
  
    for (int[] d : DIRS) {  
  
        int nr = cur[0] + d[0];  
        int nc = cur[1] + d[1];  
  
        if (nr >= 0 && nr < m &&  
                nc >= 0 && nc < n &&  
                dist[nr][nc] == -1) {  
  
            dist[nr][nc] =  
                    dist[cur[0]][cur[1]] + 1;  
  
            queue.offer(new int[]{nr,nc});  
        }  
    }  
}

dfs深度搜索

public static final int[][] DIRS = {  
        {0,-1},{0,1},{-1,0},{1,0}  
};
public void dfs(int[][] grid, int row, int col) {  
  
        int m = grid.length;  
        int n = grid[0].length;  
  
        // 越界  
        if (row < 0 || row >= m || col < 0 || col >= n) {  
            return;  
        }  
  
        // 水域 或 已访问  
        if (grid[row][col] == 1) {  
            return;  
        }  
  
        // 淹掉  
        grid[row][col] = 1;  
  
        for (int[] dir : DIRS) {  
  
            dfs(grid,  
                    row + dir[0],  
                    col + dir[1]);  
        }  
    }  
}

排序规则总结

1. Arrays.sort()

一维数组升序

Arrays.sort(nums);

自定义排序

Arrays.sort(arr, (a, b) -> 规则);

规则:

写法 含义
a - b 升序
b - a 降序

2. 二维数组排序

按第一列升序

Arrays.sort(arr, (a,b) -> a[0] - b[0]);

按第二列升序

Arrays.sort(arr, (a,b) -> a[1] - b[1]);

3. 多条件排序

Arrays.sort(arr, (a,b) -> {    if (a[0] != b[0]) {        return a[0] - b[0];    }    return a[1] - b[1];});

4. Collections.sort()

用于 List

升序

Collections.sort(list);

自定义排序

Collections.sort(list, (a,b) -> b - a);

5. list.sort()

Collections.sort() 类似,更推荐。

升序

list.sort((a,b) -> a - b);

降序

list.sort((a,b) -> b - a);

6. 返回值规则(核心)

返回值 含义
< 0 a 在前
> 0 b 在前
= 0 顺序随意

7. 推荐写法(防溢出)

Integer.compare(a, b)

例如:

Arrays.sort(arr,    (a,b) -> Integer.compare(a[0], b[0]));
posted @ 2026-07-02 17:47  畅畅c  阅读(1)  评论(0)    收藏  举报