Java集合框架核心组件

📌 学习目标:深入理解Java集合框架的设计哲学,掌握List、Set、Map三大体系的核心实现原理与性能差异,学会在真实业务场景中做出最优选型决策。
🔑 重点ArrayList vs LinkedList 底层结构差异与适用边界HashSet/LinkedHashSet/TreeSet 去重机制与排序策略HashMap 扩容机制与线程安全问题Stream API 函数式遍历Collections工具类与并发集合简介


一、集合框架全景图:为什么需要集合?

在Java中,数组的长度是固定的,无法动态扩容。当我们需要存储数量不确定的数据时,集合框架(Java Collections Framework)应运而生。它提供了一套标准化的数据结构,让我们能够高效地增删改查数据。

1.1 集合框架的继承体系

Java集合框架的核心位于 java.util 包下,主要分为两大阵营:

  • Collection 接口家族 :存储单个元素的集合

    • List:有序、可重复
    • Set:无序、不可重复
    • Queue:队列(FIFO)
  • Map 接口家族:存储键值对(Key-Value)

    复制代码
                      Iterable
                         │
                   Collection                      Map
                  /    │    \                    /  \
              List   Set   Queue              HashMap
             /  \   / | \   /  \             /    \
        ArrayList LinkedList HashSet LinkedHashSet TreeMap
                    TreeSet  PriorityQueue       LinkedHashMap

💡 设计思想:接口定义规范,实现类提供具体的数据结构。这种"面向接口编程"的设计让我们可以轻松切换底层实现,而无需修改业务代码。


二、List:有序列表的两种灵魂

List 是有序集合,允许元素重复,支持通过索引(下标)访问元素。

2.1 ArrayList:数组的"动态升级版"

底层结构 :基于Object数组实现,初始容量默认为10,扩容时增长为原来的1.5倍。

时间复杂度分析

操作 时间复杂度 说明
查询(get) O(1) 直接通过数组索引访问
尾部插入(add) 均摊 O(1) 偶尔触发扩容,需要数组拷贝
中间插入/删除 O(n) 需要移动后续所有元素

适用场景:读多写少、频繁随机访问、数据量已知或可预估。

java 复制代码
import java.util.ArrayList;
import java.util.List;

public class ArrayListDemo {
    public static void main(String[] args) {
        // 推荐:指定初始容量,避免频繁扩容
        List<String> books = new ArrayList<>(100);

        books.add("Java核心技术");
        books.add("Effective Java");
        books.add("深入理解JVM");
        books.add("Spring实战");

        // 随机访问 --- O(1)
        System.out.println("第2本书:" + books.get(1));

        // 批量添加
        List<String> moreBooks = List.of("Redis设计与实现", "MySQL必知必会");
        books.addAll(moreBooks);

        // 遍历方式1:for-each(最常用)
        System.out.println("\n=== 书单 ===");
        for (String book : books) {
            System.out.println("📖 " + book);
        }

        // 遍历方式2:Lambda表达式(Java 8+)
        System.out.println("\n=== Lambda遍历 ===");
        books.forEach(book -> System.out.println("📚 " + book));

        // 遍历方式3:Stream过滤
        System.out.println("\n=== 过滤出含Java的书 ===");
        books.stream()
             .filter(b -> b.contains("Java"))
             .forEach(System.out::println);
    }
}

输出

复制代码
第2本书:Effective Java

=== 书单 ===
📖 Java核心技术
📖 Effective Java
📖 深入理解JVM
📖 Spring实战
📖 Redis设计与实现
📖 MySQL必知必会

=== Lambda遍历 ===
📚 Java核心技术
📚 Effective Java
📚 深入理解JVM
📚 Spring实战
📚 Redis设计与实现
📚 MySQL必知必会

=== 过滤出含Java的书 ===
Java核心技术
Effective Java

2.2 LinkedList:链表的"双向魅力"

底层结构 :基于双向链表实现,每个节点包含:前驱指针、数据、后继指针。

时间复杂度分析

操作 时间复杂度 说明
查询(get) O(n) 需要从头/尾遍历到目标位置
头部/尾部插入删除 O(1) 只需修改指针指向
中间插入/删除 O(n) 先遍历到位置,再修改指针

适用场景:频繁在头部/尾部操作、实现队列/栈结构、数据量较小。

java 复制代码
import java.util.LinkedList;
import java.util.List;

public class LinkedListDemo {
    public static void main(String[] args) {
        // LinkedList 同时实现了 List 和 Deque 接口
        LinkedList<String> queue = new LinkedList<>();

        // 模拟消息队列:生产者入队
        queue.offer("订单消息-001");
        queue.offer("订单消息-002");
        queue.offer("订单消息-003");

        System.out.println("队列内容:" + queue);

        // 消费者出队 --- 先进先出
        while (!queue.isEmpty()) {
            String msg = queue.poll();  // 取出并移除队首
            System.out.println("处理消息:" + msg);
        }

        // 作为栈使用 --- 后进先出
        LinkedList<String> stack = new LinkedList<>();
        stack.push("第一层");
        stack.push("第二层");
        stack.push("第三层");

        System.out.println("\n=== 栈弹出 ===");
        while (!stack.isEmpty()) {
            System.out.println("弹出:" + stack.pop());
        }
    }
}

输出

复制代码
队列内容:[订单消息-001, 订单消息-002, 订单消息-003]
处理消息:订单消息-001
处理消息:订单消息-002
处理消息:订单消息-003

=== 栈弹出 ===
弹出:第三层
弹出:第二层
弹出:第一层

2.3 ArrayList vs LinkedList 选型指南

复制代码
┌─────────────────────────────────────────────────────────────┐
│  场景                        │  推荐选择                     │
├─────────────────────────────────────────────────────────────┤
│  频繁随机访问(get/indexOf)  │  ✅ ArrayList                 │
│  频繁在头部/尾部插入删除      │  ✅ LinkedList                │
│  数据量很大且内存敏感         │  ❌ ArrayList(扩容浪费内存)   │
│  需要实现队列/栈             │  ✅ LinkedList(天然支持)     │
│  遍历为主,偶尔增删           │  ✅ ArrayList                 │
│  已知数据量,一次性初始化     │  ✅ ArrayList(指定容量)      │
└─────────────────────────────────────────────────────────────┘

⚠️ 注意:现代JVM对ArrayList的优化已经非常成熟,除非明确需要队列/栈特性,否则大多数场景优先选择ArrayList。


三、Set:去重集合的三种性格

Set 的核心特性是不允许重复元素 。判断是否重复的标准是 equals()hashCode() 方法。

3.1 HashSet:最快的去重方案

底层结构 :基于 HashMap 实现,元素作为Key存储,Value是一个固定的Object占位符。

核心机制

  • 添加元素时,计算 hashCode() 定位桶位置
  • 如果桶内有元素,调用 equals() 判断是否重复
  • 不重复则链式存储(JDK 8+ 链表长度>8时转为红黑树)

特点 :无序、去重、O(1) 增删查、非线程安全

java 复制代码
import java.util.HashSet;
import java.util.Set;

public class HashSetDemo {
    public static void main(String[] args) {
        Set<String> tags = new HashSet<>();

        // 添加标签
        tags.add("Java");
        tags.add("Spring");
        tags.add("MySQL");
        tags.add("Java");  // 重复,自动忽略

        System.out.println("标签集合:" + tags);
        System.out.println("数量:" + tags.size());  // 3,不是4

        // 判断是否存在
        System.out.println("包含Java?" + tags.contains("Java"));  // true

        // 批量操作
        Set<String> newTags = Set.of("Redis", "Java", "Kafka");

        // 交集
        Set<String> intersection = new HashSet<>(tags);
        intersection.retainAll(newTags);
        System.out.println("交集:" + intersection);

        // 并集
        Set<String> union = new HashSet<>(tags);
        union.addAll(newTags);
        System.out.println("并集:" + union);
    }
}

输出

复制代码
标签集合:[Java, Spring, MySQL]
数量:3
包含Java?true
交集:[Java]
并集:[Java, Spring, MySQL, Redis, Kafka]

3.2 LinkedHashSet:记住你来时的顺序

底层结构:HashSet + 双向链表,在HashSet的基础上维护了一个插入顺序链表。

特点 :按插入顺序遍历、去重、比HashSet略慢(维护链表有额外开销)。

java 复制代码
import java.util.LinkedHashSet;
import java.util.Set;

public class LinkedHashSetDemo {
    public static void main(String[] args) {
        // 需要保持插入顺序时使用
        Set<String> history = new LinkedHashSet<>();

        history.add("首页");
        history.add("商品列表");
        history.add("商品详情");
        history.add("购物车");
        history.add("结算页");

        System.out.println("浏览历史(按访问顺序):");
        history.forEach(page -> System.out.println("→ " + page));

        // 模拟后退:移除最后访问的页面
        // LinkedHashSet 没有直接移除最后一个的方法,但维护了顺序
    }
}

3.3 TreeSet:自动排序的集合

底层结构 :基于 红黑树(自平衡二叉搜索树)实现。

特点 :元素按自然顺序自定义比较器排序、去重、O(log n) 增删查。

java 复制代码
import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetDemo {
    public static void main(String[] args) {
        // 自然排序(String按字典序)
        TreeSet<String> words = new TreeSet<>();
        words.add("banana");
        words.add("apple");
        words.add("cherry");
        words.add("date");

        System.out.println("自然排序:" + words);

        // 自定义排序:按字符串长度降序
        TreeSet<String> byLength = new TreeSet<>(Comparator.comparingInt(String::length).reversed());
        byLength.add("hi");
        byLength.add("hello");
        byLength.add("hey");
        byLength.add("goodbye");

        System.out.println("按长度降序:" + byLength);

        // 范围查询:TreeSet的强大功能
        TreeSet<Integer> scores = new TreeSet<>();
        scores.add(85);
        scores.add(92);
        scores.add(78);
        scores.add(95);
        scores.add(88);

        System.out.println("\n成绩区间查询:");
        System.out.println("大于等于90的:" + scores.tailSet(90));      // [92, 95]
        System.out.println("小于90的:" + scores.headSet(90));         // [78, 85, 88]
        System.out.println("80到90之间的:" + scores.subSet(80, 90));  // [85, 88]
    }
}

输出

复制代码
自然排序:[apple, banana, cherry, date]
按长度降序:[goodbye, hello, hey, hi]

成绩区间查询:
大于等于90的:[92, 95]
小于90的:[78, 85, 88]
80到90之间的:[85, 88]

3.4 Set 选型速查表

实现类 有序性 去重方式 时间复杂度 适用场景
HashSet 无序 hashCode+equals O(1) 仅需去重,不关心顺序
LinkedHashSet 插入顺序 hashCode+equals O(1) 需要去重且保留插入顺序
TreeSet 排序顺序 compareTo/compare O(log n) 需要去重且需要排序/范围查询

四、Map:键值对的智慧

Map 存储的是键值对(Key-Value),Key 唯一,Value 可重复。它是Java中使用最频繁的集合类型之一。

4.1 HashMap:最经典的键值对存储

底层结构:数组 + 链表/红黑树(JDK 8+)。

核心参数

  • 初始容量:默认16,必须是2的幂次方(方便位运算取模)
  • 加载因子:默认0.75,即当元素数量 > 容量 × 0.75 时触发扩容
  • 扩容机制:容量翻倍,所有元素重新计算hash位置(rehash)

hash冲突解决

  • 链表长度 < 8:使用链表
  • 链表长度 ≥ 8 且数组长度 ≥ 64:链表转为红黑树
  • 红黑树节点 < 6:退化为链表
java 复制代码
import java.util.HashMap;
import java.util.Map;

public class HashMapDemo {
    public static void main(String[] args) {
        // 学生成绩表:学号 -> 成绩
        Map<String, Integer> scores = new HashMap<>(16, 0.75f);

        scores.put("2024001", 85);
        scores.put("2024002", 92);
        scores.put("2024003", 78);
        scores.put("2024004", 95);

        // 查询
        System.out.println("学号2024002的成绩:" + scores.get("2024002"));

        // 不存在时返回默认值
        System.out.println("学号2024999的成绩:" + scores.getOrDefault("2024999", 0));

        // 遍历方式1:EntrySet(效率最高)
        System.out.println("\n=== 成绩明细 ===");
        for (Map.Entry<String, Integer> entry : scores.entrySet()) {
            System.out.printf("学号:%s,成绩:%d%n", entry.getKey(), entry.getValue());
        }

        // 遍历方式2:Java 8 Lambda
        System.out.println("\n=== Lambda遍历 ===");
        scores.forEach((id, score) -> 
            System.out.printf("学号:%s,成绩:%d%n", id, score)
        );

        // 遍历方式3:KeySet遍历
        System.out.println("\n=== 所有学号 ===");
        scores.keySet().forEach(System.out::println);

        // 计算操作:不存在则放入,存在则更新
        scores.merge("2024001", 5, Integer::sum);  // 85 + 5 = 90
        System.out.println("\n更新后2024001的成绩:" + scores.get("2024001"));
    }
}

输出

复制代码
学号2024002的成绩:92
学号2024999的成绩:0

=== 成绩明细 ===
学号:2024001,成绩:85
学号:2024002,成绩:92
学号:2024003,成绩:78
学号:2024004,成绩:95

=== Lambda遍历 ===
学号:2024001,成绩:85
学号:2024002,成绩:92
学号:2024003,成绩:78
学号:2024004,成绩:95

=== 所有学号 ===
2024001
2024002
2024003
2024004

更新后2024001的成绩:90

4.2 LinkedHashMap:有序的HashMap

特点:继承自HashMap,额外维护了一个双向链表记录插入顺序(或访问顺序)。

java 复制代码
import java.util.LinkedHashMap;
import java.util.Map;

public class LinkedHashMapDemo {
    public static void main(String[] args) {
        // accessOrder = true:按访问顺序排序(LRU缓存的基础)
        Map<String, String> cache = new LinkedHashMap<>(16, 0.75f, true) {
            @Override
            protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
                // 当容量超过3时,移除最久未访问的元素
                return size() > 3;
            }
        };

        cache.put("A", "数据A");
        cache.put("B", "数据B");
        cache.put("C", "数据C");

        System.out.println("初始缓存:" + cache.keySet());

        // 访问A,A变为最近使用
        cache.get("A");
        System.out.println("访问A后:" + cache.keySet());

        // 添加D,超出容量,移除最久未使用的B
        cache.put("D", "数据D");
        System.out.println("添加D后:" + cache.keySet());
    }
}

输出

复制代码
初始缓存:[A, B, C]
访问A后:[B, C, A]
添加D后:[C, A, D]

4.3 TreeMap:排序的键值对

特点:基于红黑树,Key按自然顺序或自定义比较器排序,支持范围查询。

java 复制代码
import java.util.TreeMap;
import java.util.Map;

public class TreeMapDemo {
    public static void main(String[] args) {
        // 按价格排序的商品目录
        TreeMap<Double, String> menu = new TreeMap<>();

        menu.put(12.0, "宫保鸡丁");
        menu.put(8.0, "酸辣土豆丝");
        menu.put(28.0, "水煮鱼");
        menu.put(18.0, "糖醋排骨");
        menu.put(6.0, "米饭");

        System.out.println("=== 菜单(按价格升序)===");
        menu.forEach((price, dish) -> 
            System.out.printf("¥%.1f --- %s%n", price, dish)
        );

        // 价格区间查询
        System.out.println("\n10元以下的菜:" + menu.headMap(10.0));
        System.out.println("15元以上的菜:" + menu.tailMap(15.0));
        System.out.println("10-20元的菜:" + menu.subMap(10.0, 20.0));

        // 最接近某价格的菜
        System.out.println("\n最接近15元的菜:" + menu.ceilingEntry(15.0));  // ≥15的最小值
        System.out.println("最接近15元的菜(向下):" + menu.floorEntry(15.0));  // ≤15的最大值
    }
}

输出

复制代码
=== 菜单(按价格升序)===
¥6.0 --- 米饭
¥8.0 --- 酸辣土豆丝
¥12.0 --- 宫保鸡丁
¥18.0 --- 糖醋排骨
¥28.0 --- 水煮鱼

10元以下的菜:{6.0=米饭, 8.0=酸辣土豆丝}
15元以上的菜:{18.0=糖醋排骨, 28.0=水煮鱼}
10-20元的菜:{12.0=宫保鸡丁, 18.0=糖醋排骨}

最接近15元的菜:18.0=糖醋排骨
最接近15元的菜(向下):12.0=宫保鸡丁

4.4 Map 选型速查表

实现类 Key有序性 时间复杂度 特殊能力 适用场景
HashMap 无序 O(1) 通用键值存储
LinkedHashMap 插入/访问顺序 O(1) LRU缓存 需要顺序或缓存
TreeMap 排序顺序 O(log n) 范围查询 需要排序或区间查找
ConcurrentHashMap 无序 O(1) 线程安全 并发环境

五、现代遍历方式:Stream API

Java 8 引入的 Stream API 让集合操作更加函数式和声明式。

java 复制代码
import java.util.*;
import java.util.stream.Collectors;

public class StreamDemo {
    public static void main(String[] args) {
        List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

        // 过滤 + 映射 + 收集
        List<Integer> evenSquares = numbers.stream()
            .filter(n -> n % 2 == 0)      // 过滤偶数
            .map(n -> n * n)               // 平方
            .collect(Collectors.toList()); // 收集为List

        System.out.println("偶数的平方:" + evenSquares);

        // 分组
        List<String> names = List.of("Alice", "Bob", "Anna", "Bill", "Amy");
        Map<Character, List<String>> grouped = names.stream()
            .collect(Collectors.groupingBy(s -> s.charAt(0)));

        System.out.println("\n按首字母分组:" + grouped);

        // 统计
        IntSummaryStatistics stats = numbers.stream()
            .mapToInt(Integer::intValue)
            .summaryStatistics();

        System.out.println("\n统计信息:");
        System.out.println("数量:" + stats.getCount());
        System.out.println("总和:" + stats.getSum());
        System.out.println("平均:" + stats.getAverage());
        System.out.println("最大:" + stats.getMax());
        System.out.println("最小:" + stats.getMin());
    }
}

输出

复制代码
偶数的平方:[4, 16, 36, 64, 100]

按首字母分组:{A=[Alice, Anna, Amy], B=[Bob, Bill]}

统计信息:
数量:10
总和:55
平均:5.5
最大:10
最小:1

六、实战:电商订单系统

综合运用集合框架实现一个简化的电商订单管理系统。

java 复制代码
import java.util.*;
import java.util.stream.Collectors;

// 商品类
class Product {
    private String id;
    private String name;
    private double price;
    private String category;

    public Product(String id, String name, double price, String category) {
        this.id = id; this.name = name; this.price = price; this.category = category;
    }
    public String getId() { return id; }
    public String getName() { return name; }
    public double getPrice() { return price; }
    public String getCategory() { return category; }
    @Override public String toString() { return name + "(¥" + price + ")"; }
}

// 订单项
class OrderItem {
    private Product product;
    private int quantity;

    public OrderItem(Product product, int quantity) {
        this.product = product; this.quantity = quantity;
    }
    public double getSubtotal() { return product.getPrice() * quantity; }
    public Product getProduct() { return product; }
    public int getQuantity() { return quantity; }
}

// 订单
class Order {
    private String orderId;
    private List<OrderItem> items;
    private long createTime;

    public Order(String orderId) {
        this.orderId = orderId;
        this.items = new ArrayList<>();
        this.createTime = System.currentTimeMillis();
    }

    public void addItem(Product product, int quantity) {
        items.add(new OrderItem(product, quantity));
    }

    public double getTotal() {
        return items.stream().mapToDouble(OrderItem::getSubtotal).sum();
    }

    public String getOrderId() { return orderId; }
    public List<OrderItem> getItems() { return items; }
}

// 订单管理系统
public class OrderSystem {
    public static void main(String[] args) {
        // 商品库:使用HashMap快速查找
        Map<String, Product> productMap = new HashMap<>();
        productMap.put("P001", new Product("P001", "iPhone 15", 5999.0, "手机"));
        productMap.put("P002", new Product("P002", "MacBook Pro", 14999.0, "电脑"));
        productMap.put("P003", new Product("P003", "AirPods Pro", 1899.0, "配件"));
        productMap.put("P004", new Product("P004", "iPad Air", 4799.0, "平板"));
        productMap.put("P005", new Product("P005", "小米14", 3999.0, "手机"));

        // 创建订单
        List<Order> orders = new ArrayList<>();

        Order order1 = new Order("O20240522001");
        order1.addItem(productMap.get("P001"), 1);
        order1.addItem(productMap.get("P003"), 2);
        orders.add(order1);

        Order order2 = new Order("O20240522002");
        order2.addItem(productMap.get("P002"), 1);
        order2.addItem(productMap.get("P004"), 1);
        orders.add(order2);

        Order order3 = new Order("O20240522003");
        order3.addItem(productMap.get("P005"), 2);
        orders.add(order3);

        // 统计:按品类汇总销售额
        System.out.println("=== 品类销售统计 ===");
        Map<String, Double> categorySales = new HashMap<>();

        for (Order order : orders) {
            for (OrderItem item : order.getItems()) {
                String category = item.getProduct().getCategory();
                categorySales.merge(category, item.getSubtotal(), Double::sum);
            }
        }

        categorySales.entrySet().stream()
            .sorted(Map.Entry.<String, Double>comparingByValue().reversed())
            .forEach(e -> System.out.printf("%s:¥%.2f%n", e.getKey(), e.getValue()));

        // 统计:找出最畅销的商品
        System.out.println("\n=== 商品销量排行 ===");
        Map<String, Integer> productSales = new HashMap<>();

        for (Order order : orders) {
            for (OrderItem item : order.getItems()) {
                productSales.merge(item.getProduct().getName(), item.getQuantity(), Integer::sum);
            }
        }

        productSales.entrySet().stream()
            .sorted(Map.Entry.<String, Integer>comparingByValue().reversed())
            .forEach(e -> System.out.printf("%s:%d件%n", e.getKey(), e.getValue()));

        // 订单总金额
        System.out.println("\n=== 订单汇总 ===");
        double totalRevenue = orders.stream().mapToDouble(Order::getTotal).sum();
        System.out.printf("总订单数:%d%n", orders.size());
        System.out.printf("总销售额:¥%.2f%n", totalRevenue);
        System.out.printf("平均客单价:¥%.2f%n", totalRevenue / orders.size());
    }
}

输出

复制代码
=== 品类销售统计 ===
电脑:¥14999.00
手机:¥13997.00
配件:¥3798.00
平板:¥4799.00

=== 商品销量排行 ===
AirPods Pro:2件
小米14:2件
iPhone 15:1件
MacBook Pro:1件
iPad Air:1件

=== 订单汇总 ===
总订单数:3
总销售额:¥37593.00
平均客单价:¥12531.00

七、避坑指南:集合使用常见陷阱

7.1 并发修改异常

java 复制代码
List<String> list = new ArrayList<>(List.of("A", "B", "C"));

// ❌ 错误:遍历时直接删除
for (String s : list) {
    if (s.equals("B")) list.remove(s);  // 抛出 ConcurrentModificationException
}

// ✅ 正确:使用迭代器的remove方法
Iterator<String> it = list.iterator();
while (it.hasNext()) {
    if (it.next().equals("B")) it.remove();
}

// ✅ 更优雅:使用removeIf(Java 8+)
list.removeIf(s -> s.equals("B"));

7.2 HashMap的Key可变性问题

java 复制代码
// ❌ 错误:使用可变对象作为Key
Map<List<String>, String> badMap = new HashMap<>();
List<String> key = new ArrayList<>(List.of("a", "b"));
badMap.put(key, "value");
key.add("c");  // 修改了Key!
// 此时再也找不到这个Entry了,因为hashCode变了

// ✅ 正确:使用不可变对象作为Key
Map<String, String> goodMap = new HashMap<>();

7.3 自动装箱的性能陷阱

java 复制代码
// ❌ 低效:频繁自动装箱
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 1000000; i++) {
    list.add(i);  // int -> Integer 装箱
}

// ✅ 高效:使用基本类型集合(第三方库如fastutil,或Java原生的IntStream)
IntStream.range(0, 1000000).boxed().collect(Collectors.toList());

八、总结与选型速查

需求 推荐集合 理由
有序列表,读多写少 ArrayList 随机访问O(1)
队列/栈,头尾操作 LinkedList 双端操作O(1)
快速去重 HashSet 增删查O(1)
去重+保留顺序 LinkedHashSet 插入顺序
去重+排序 TreeSet 自然排序
通用键值存储 HashMap 增删查O(1)
键值存储+顺序 LinkedHashMap LRU缓存
键值存储+排序 TreeMap 范围查询
并发环境 ConcurrentHashMap 线程安全
不可变集合 List.of() / Map.of() 安全、高效
相关推荐
我是一颗柠檬12 小时前
【JDK8新特性】Stream流API上Day4
java·开发语言·后端
超梦dasgg12 小时前
拆分大对象 + 流式处理 + 不一次性加载全量数据
java·jvm·windows
我是一颗柠檬12 小时前
【JDK8新特性】方法引用与构造器引用Day3
java·开发语言·后端·intellij-idea
在繁华处12 小时前
从零搭建轻灵(五):记忆系统与生产化特性
java·jvm·oracle
天若有情67312 小时前
Deepseek-V4-Flash-20260423 深度评测与实战指南
java·大数据·网络·ai
折哥的程序人生 · 物流技术专研12 小时前
《Java 100 天进阶之路》第32篇:Java常用工具类(Objects、Collections、Arrays深入)
java·后端·面试·求职招聘
憧憬成为java架构高手的小白12 小时前
苍穹外卖项目-day02
java·spring
西凉的悲伤13 小时前
SpringBoot RestTemplate 介绍
java·spring boot·后端·resttemplate
Roselind_Yi14 小时前
池化对比:CNN池化 VS Java线程池
java·人工智能·经验分享·笔记·深度学习·神经网络·cnn