导入包:import java.util.*

简单数组

1
2
3
4
5
s.toCharArray(); // 返回char[] , 例如:[1,a,2,c]
Arrays.equals(arr1,arr2) //方法是比较数组中的元素(含位置)是否相同,不是地址
Arrays.deepEquals()// 多维数组比较

Arrays.sort(intervals, (p, q) -> p[0] - q[0]);// 如果是二维数组,如何按左端点排序?

字符串

1
2
3
4
5
6
7
8
9
10
11
12
String s="1a2c"

s.charAt(0) //获取0号下标的char

s.toCharArray(); // 返回char[] , 例如:[1,a,2,c]
String key = new String(array);// char[]转字符串

s.indexOf('a')// 查找‘a’的元素位置
s.indexOf('a',2)// 从2号下标开始查找'a'的位置
s.indexOf("SUBSTRING")// 查找给定子串在元素位置
s.indexOf("SUBSTRING",2)// 从2号下标开始查找给定子串在元素位置
s.substring(1,2)// 左闭右开,都是下标

集合

一、集合框架核心接口

List

  1. 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
    32
      List<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); // 比较元素和位置,但不比较地址

  2. ArrayList

    1
    new ArrayList<Integer>(List.of(x, y,z)) //生成一个list,包含[x,y,z],并转为arraylist
  3. 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

  1. Set 集合(无序唯一)
    1
    2
    3
    4
    Set<Integer> set = new HashSet<>();
    set.add(10); // 添加元素(自动去重)
    set.contains(10); // 存在性检查
    set1.equals(set2); // 仅比较元素

Map

  1. 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
    36
      Map<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

  1. Queue 队列

    1
    2
    3
    4
      Queue<String> queue = new LinkedList<>(); // 注意是LinkedList实现的
    queue.offer("first")/.add("first"); // 入队
    queue.poll(); // 出队
    queue.peek(); // 获取第一个,但不出队
  2. PriorityQueue 队列

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    PriorityQueue<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>() {
    @Override
    public int compare(Integer o1, Integer o2) {
    return o2.compareTo(o1); // 降序排列
    }
    });// 如果不写:**默认是最小的元素在前**

  3. 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排序

三、关键工具类语法

  1. 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>() {
    @Override 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);
  2. 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
2
3
4
5
List<String> names = List.of("Alice", "Bob", "Charlie");
List<Integer> lengths = names.stream()
.filter(name -> name.length() > 3)
.map(String::length)
.toList(); // 结果: [5, 7]

2. 扁平化处理嵌套集合

1
2
3
4
List<List<Integer>> nestedList = List.of(List.of(1,2), List.of(3,4));
List<Integer> flatList = nestedList.stream()
.flatMap(List::stream)
.toList(); // 结果: [1,2,3,4]

3. 统计操作

1
2
3
long count = Stream.of("apple", "banana", "orange")
.filter(fruit -> fruit.contains("a"))
.count(); // 结果: 3

4. 归约求和

1
2
int sum = IntStream.range(1, 5) // 1,2,3,4
.reduce(0, Integer::sum); // 结果: 10

输入输出

1
2
3
4
5
6
7
8
9
10
11
12
Scanner scanner = new Scanner(System.in);
while(scanner.hasNext()){
String str = scanner.nextLine();

String[] strs = str.split(" ");
Arrays.sort(strs);
System.out.println(String.join(" ",strs));
}



int number = Integer.parseInt(numberStr);

板子

【二分】闭区间

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
35
public 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];
}