Java 常用集合框架手册

概述

Java 集合框架主要分为三大类:

  • List:有序、可重复
  • Set:无序、不可重复
  • Map:键值对存储

List 列表

ArrayList

基于动态数组实现,查询快,增删慢。

操作 时间复杂度
get(index) O(1)
add(e) O(1) 平均
add(index, e) O(n)
remove(index) O(n)

常用方法

csharp 复制代码
List<String> list = new ArrayList<>();

// 添加
list.add("a");
list.add(1, "b");  // 插入到指定位置

// 查询
list.get(0);
list.size();
list.contains("a");
list.indexOf("a");

// 修改
list.set(0, "new");

// 删除
list.remove("a");
list.remove(0);  // 删除指定索引
list.clear();

// 遍历
for (String s : list) {}
list.forEach(System.out::println);

LinkedList

基于双向链表实现,增删快,查询慢。

操作 时间复杂度
get(index) O(n)
add(e) O(1)
addFirst/e O(1)
removeFirst/Last O(1)

常用方法

ini 复制代码
LinkedList<String> list = new LinkedList<>();

// 队列/栈操作
list.addFirst("a");
list.addLast("b");
list.removeFirst();
list.removeLast();
list.peekFirst();
list.peekLast();

// List 操作
list.add("c");
list.get(0);
list.remove("c");

ArrayList vs LinkedList

特性 ArrayList LinkedList
底层结构 动态数组 双向链表
查询 快 O(1) 慢 O(n)
增删 慢 O(n) 快 O(1)
内存占用 多(需存储前后指针)
适用场景 频繁查询 频繁增删

Queue 队列

ArrayDeque

基于动态数组的双端队列,推荐作为队列使用。

arduino 复制代码
Queue<String> queue = new ArrayDeque<>();

// 入队
queue.offer("a");      // 推荐
queue.add("b");        // 失败抛异常

// 出队
queue.poll();          // 推荐,失败返回 null
queue.remove();        // 失败抛异常
queue.peek();          // 查看队首,不删除

PriorityQueue

优先队列,基于堆实现,元素按自然顺序或比较器排序。

ini 复制代码
Queue<Integer> pq = new PriorityQueue<>();

pq.offer(3);
pq.offer(1);
pq.offer(2);

// 每次取出最小值
pq.poll();  // 1
pq.poll();  // 2
pq.poll();  // 3

// 自定义比较器(大顶堆)
Queue<Integer> maxHeap = new PriorityQueue<>(Collections.reverseOrder());
Queue<Integer> maxHeap = new PriorityQueue<>((o1, o2) -> o2 - o1);

//默认为最小堆
Queue<Integer> minHeap = new PriorityQueue<>();
Queue<Integer> maxHeap = new PriorityQueue<>((o1, o2) -> o1 - o2);

LinkedList 作为队列

arduino 复制代码
Queue<String> queue = new LinkedList<>();
queue.offer("a");
queue.poll();

Map 键值对

HashMap

基于哈希表实现,键无序,允许 null 键和 null 值。

arduino 复制代码
Map<String, Integer> map = new HashMap<>();

// 添加
map.put("a", 1);
map.put("b", 2);

// 查询
map.get("a");
map.containsKey("a");
map.containsValue(1);
map.size();

// 删除
map.remove("a");
map.clear();

// 遍历:键值对遍历要先变成Entry集合
for (Map.Entry<String, Integer> e : map.entrySet()) {
    System.out.println(e.getKey() + ": " + e.getValue());
}

map.forEach((k, v) -> System.out.println(k + ": " + v));

LinkedHashMap

保持插入顺序的 HashMap。

arduino 复制代码
Map<String, Integer> map = new LinkedHashMap<>();
map.put("a", 1);
map.put("b", 2);
// 遍历时按插入顺序:a, b

TreeMap

基于红黑树实现,键按自然顺序或比较器排序。

arduino 复制代码
Map<String, Integer> map = new TreeMap<>();
map.put("c", 3);
map.put("a", 1);
map.put("b", 2);

// 遍历时按键排序:a, b, c

// 常用方法
map.firstKey();    // 最小键
map.lastKey();     // 最大键
map.subMap("a", "b");  // a <= key < b 的子 map
map.headMap("b");  // key < b 的子 map
map.tailMap("b");  // key >= b 的子 map

Set 集合

HashSet

基于 HashMap 实现,元素无序且不可重复。

dart 复制代码
Set<String> set = new HashSet<>();

set.add("a");
set.remove("a");
set.contains("a");
set.size();
set.clear();

for (String s : set) {}

LinkedHashSet

保持插入顺序的 HashSet。

csharp 复制代码
Set<String> set = new LinkedHashSet<>();
set.add("a");
set.add("b");
// 遍历按插入顺序

TreeSet

基于红黑树实现,元素按自然顺序或比较器排序,不可重复。

csharp 复制代码
Set<Integer> set = new TreeSet<>();

set.add(3);
set.add(1);
set.add(2);

// 遍历按排序:1, 2, 3

set.first();    // 最小元素
set.last();     // 最大元素
set.headSet(2); // < 2 的子 set
set.tailSet(2); // >= 2 的子 set
set.subSet(1, 3); // 1 <= x < 3 的子 set

Java 泛型 <T>

泛型提供编译时类型安全,避免类型转换。

typescript 复制代码
// 自定义泛型类
class Box<T> {
    private T value;
    
    public void set(T value) { this.value = value; }
    public T get() { return value; }
}

Box<String> box = new Box<>();
box.set("hello");
String s = box.get();

// 泛型方法
public <T> T first(List<T> list) {
    return list.get(0);
}

// 通配符
List<? extends Number> list1;  // Number 的子类
List<? super Integer> list2;   // Integer 的父类
List<?> list3;                 // 任意类型

迭代器 Iterator & Iterable

Iterator

用于遍历集合的元素。

ini 复制代码
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");

// 迭代器遍历
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    String s = it.next();
    if ("a".equals(s)) {
        it.remove();  // 安全删除
    }
}

Iterable

实现 Iterable 接口的类可以使用 for-each 循环。

typescript 复制代码
// for-each 等价于 iterator
for (String s : list) {
    System.out.println(s);
}

// 自定义可迭代类
class MyCollection implements Iterable<String> {
    private List<String> data = new ArrayList<>();
    
    public void add(String s) { data.add(s); }
    
    @Override
    public Iterator<String> iterator() {
        return data.iterator();
    }
}

MyCollection col = new MyCollection();
col.add("a");
for (String s : col) {}  // 可用 for-each

Stream

数据源.零个或多个中间操作.最终操作

中间操作:

  • filter:过滤元素
  • map:类型 / 数值转换
  • distinct:去重
  • sorted:排序
  • limit:截取前 n 个
  • skip:跳过前 n 个
  • flatMap :拆分嵌套集合
    最终操作:
  • collect:收集为集合(最常用)
  • forEach:遍历输出
  • count:统计数量
  • max/min:取最大最小值
  • sum:求和(数值流)
  • anyMatch/allMatch/noneMatch:条件匹配返回布尔:任意、全部、都不满足
  • findFirst/findAny :获取元素:取首个、取随机
    没什么好说的,上题目

前置

ini 复制代码
List<Integer> numList = Arrays.asList(1,2,3,4,5,6,7,8,9,10); 
List<String> nameList = Arrays.asList("张三","李四","张无忌","赵敏","张三丰");

实现

ini 复制代码
public class StreamTest {  
    public static void main(String[] args) {  
        List<Integer> numList = Arrays.asList(1,2,3,4,5,6,7,8,9,10);  
        List<String> nameList = Arrays.asList("张三","李四","张无忌","张无忌","赵敏","张三丰");  
        //排除偶数 --filter        List<Integer> collect = numList.stream().filter(num -> num % 2 != 0).collect(Collectors.toList());  
        System.out.println(collect);  
        //数字全部翻倍 --map转换  
        List<Integer> collect1 = numList.stream().map(num -> num * 2).collect(Collectors.toList());  
        System.out.println(collect1);  
        //排除姓张的名字  
        List<String> collect2 = nameList.stream().filter(name -> !name.matches("^张.*")).collect(Collectors.toList());  
        System.out.println(collect2);  
        //去重  
        List<String> collect3 = nameList.stream().distinct().collect(Collectors.toList());  
        System.out.println(collect3);  
        //排序(升序 / 降序)  
        List<Integer> collect4 = numList.stream().sorted().collect(Collectors.toList());  
        List<Integer> collect5 = numList.stream().sorted((a, b) -> b - a).collect(Collectors.toList());  
        System.out.println(collect4);  
        System.out.println(collect5);  
        //取前 3 个元素 --limit        List<String> collect6 = nameList.stream().limit(3).collect(Collectors.toList());  
        System.out.println(collect6);  
        //跳过前 2 个 --skip        List<String> collect7 = nameList.stream().skip(2).collect(Collectors.toList());  
        System.out.println(collect7);  
        //求和 --mapToInt        int sum = numList.stream().mapToInt(num -> num).sum();  
        System.out.println(sum);  
        //统计元素个数  
        long count = nameList.stream().count();  
        System.out.println(count);  
        //拼接字符串  
        String collect8 = nameList.stream().collect(Collectors.joining(","));  
        System.out.println(collect8);  
    }  
}

结果

css 复制代码
[1, 3, 5, 7, 9]
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
[李四, 赵敏]
[张三, 李四, 张无忌, 赵敏, 张三丰]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
[10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
[张三, 李四, 张无忌]
[张无忌, 张无忌, 赵敏, 张三丰]
55
6
张三,李四,张无忌,张无忌,赵敏,张三丰
相关推荐
笨蛋不要掉眼泪1 小时前
Java并发编程:线程的创建和运行
java·开发语言·jvm
九伯都1 小时前
java编写 agent 入门案例
java·开发语言
环流_1 小时前
redis:持久化rdb
java·数据库·redis
xqqxqxxq2 小时前
Java 线程池(一)
java·开发语言
Full Stack Developme2 小时前
spring-beans 解析
java·后端·spring
码农-阿杰2 小时前
生成偏向锁 + JIT
java
czt_java2 小时前
线程安全问题
java·开发语言·jvm
likerhood2 小时前
设计模式-装饰器模式(java)
java·设计模式·装饰器模式
爱学习的小可爱卢2 小时前
Java抽象类与接口:面试高频考点全解析
java·javase