Java集合框架完全指南:从入门到精通

在 Java 中,集合 是一种存储元素的容器,允许快速查找特定元素。Java 提供了丰富的集合实现类和接口,每个接口都有其特定的功能。
选择合适的集合需要考虑以下因素:

  • 数据类型和大小: 根据存储的数据类型和数量选择合适的数据结构。
  • 性能要求: 操作频率高时,优化性能的集合类很重要。
  • 同步需求:如果需要线程安全,可以选择带并发操作的支持集合。

一、集合框架全景图

1.1 集合框架体系结构

Collection接口
List有序可重复
Set无序唯一
ArrayList数组实现
LinkedList链表实现
HashSet哈希表
TreeSet红黑树
Map键值对
HashMap
TreeMap
LinkedHashMap

1.2 核心接口对比

接口特点典型实现类时间复杂度
List有序,可重复ArrayList/LinkedList随机访问O(1)/O(n)
Set无序,唯一HashSet/TreeSet添加/查找O(1)/O(logn)
Map键值对,键唯一HashMap/TreeMap添加/查找O(1)/O(logn)
Queue先进先出(FIFO)LinkedList/PriorityQueue入队出队O(1)/O(logn)

二、List接口详解

2.1 ArrayList(动态数组)

// 创建与基本操作
List<String> list = new ArrayList<>();
list.add("Apple");     // 添加元素
list.add(0, "Banana"); // 指定位置插入
String fruit = list.get(1); // 获取元素(索引从0开始)
list.remove("Apple");  // 删除元素

// 遍历方式
for (int i = 0; i < list.size(); i++) { // 随机访问
    System.out.println(list.get(i));
}

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

// 转换为数组
String[] array = list.toArray(new String[0]);

特点

  • 底层基于Object[]数组
  • 默认初始容量10,扩容1.5倍
  • 适合随机访问,插入删除效率低

2.2 LinkedList(双向链表)

List<Integer> linkedList = new LinkedList<>();
linkedList.add(10);
linkedList.addFirst(5); // 头部插入
linkedList.addLast(20); // 尾部插入

// 使用迭代器高效删除
Iterator<Integer> it = linkedList.iterator();
while (it.hasNext()) {
    if (it.next() == 10) {
        it.remove(); // 安全删除
    }
}

特点

  • 每个元素包含前后节点指针
  • 插入删除O(1),查找O(n)
  • 实现Deque接口,可用作队列/栈

三、Set接口深入解析

3.1 HashSet(哈希集合)

Set<String> names = new HashSet<>();
names.add("Alice");
names.add("Bob");
names.add("Alice"); // 重复元素被忽略

// 快速判断存在性
if (names.contains("Bob")) {
    System.out.println("Bob存在");
}

// 遍历无序
for (String name : names) {
    System.out.println(name); // 输出顺序不确定
}

实现原理

  • 基于HashMap实现(值存储于HashMap的Key)
  • 依赖hashCode()和equals()方法
  • 最佳实践:重写对象的hashCode和equals

3.2 TreeSet(有序集合)

Set<Integer> scores = new TreeSet<>();
scores.add(90);
scores.add(85);
scores.add(95);

// 自动排序遍历
for (int score : scores) {
    System.out.println(score); // 输出85,90,95
}

// 范围查询
Set<Integer> subSet = ((TreeSet<Integer>)scores).subSet(85, true, 90, true);

特点

  • 基于红黑树实现
  • 元素必须实现Comparable接口
  • 查找时间复杂度O(logn)

四、Map接口核心实现

4.1 HashMap(哈希映射)

Map<String, Integer> map = new HashMap<>();
map.put("Apple", 10);
map.put("Banana", 5);

// 获取值(注意空指针)
Integer count = map.get("Apple");

// 遍历EntrySet
for (Map.Entry<String, Integer> entry : map.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}

// Java8遍历方式
map.forEach((k, v) -> System.out.println(k + " => " + v));

重要特性

  • 初始容量16,负载因子0.75
  • 哈希冲突通过链表/红黑树解决(JDK8+)
  • Key的不可变性要求

4.2 LinkedHashMap(有序哈希映射)

Map<String, Integer> orderedMap = new LinkedHashMap<>();
orderedMap.put("A", 1);
orderedMap.put("C", 3);
orderedMap.put("B", 2);

// 保持插入顺序遍历
orderedMap.forEach((k, v) -> System.out.println(k)); // 输出A,C,B

应用场景:需要保持插入顺序的缓存系统


五、集合工具类Collections

5.1 常用工具方法

List<Integer> numbers = Arrays.asList(3,1,4,1,5,9);

// 排序
Collections.sort(numbers); // [1,1,3,4,5,9]

// 洗牌
Collections.shuffle(numbers);

// 不可变集合
List<Integer> immutable = Collections.unmodifiableList(numbers);

// 同步包装
List<Integer> syncList = Collections.synchronizedList(numbers);

5.2 集合初始化技巧

// 快速初始化List
List<String> cities = new ArrayList<>() {{
    add("北京");
    add("上海");
    add("广州");
}};

// 使用Stream初始化
List<Integer> nums = Stream.of(1,2,3).collect(Collectors.toList());

六、最佳实践指南

6.1 集合选择策略

需求场景推荐实现类理由
频繁随机访问ArrayListO(1)访问效率
频繁插入删除LinkedListO(1)插入删除
去重存储HashSetO(1)查找
需要排序TreeSet自动排序
键值对快速查找HashMap最优哈希表实现
需要插入顺序LinkedHashMap维护插入顺序

6.2 性能优化要点

  1. 设置初始容量:避免频繁扩容
    new ArrayList<>(100); // 指定初始容量
    
  2. 避免装箱开销:使用原始类型集合
    IntArrayList (Eclipse Collections)
    
  3. 选择合适迭代器
    // ArrayList使用普通for更快
    for (int i=0; i<list.size(); i++) {}
    
    // LinkedList使用迭代器更优
    Iterator<Integer> it = list.iterator();
    

6.3 线程安全方案

方案优点缺点
Vector简单易用全表锁,性能差
Collections.synchronizedXXX灵活包装同Vector
ConcurrentHashMap分段锁,高并发不保证强一致性
CopyOnWriteArrayList读无锁,写时复制内存消耗大,适合读多写少

七、常见问题解答

Q1:如何避免ConcurrentModificationException?

List<String> list = new ArrayList<>(Arrays.asList("A", "B", "C"));

// 错误方式(抛出异常)
for (String s : list) {
    if (s.equals("B")) {
        list.remove(s);
    }
}

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

Q2:HashMap与HashTable的区别?

特性HashMapHashTable
线程安全
null支持允许key/value为null不允许
迭代器fail-fast不保证
性能更高较低

通过本文的学习,您已经掌握了Java集合框架的核心知识。关键要点总结:

  1. List:有序集合首选ArrayList,频繁插入删除用LinkedList
  2. Set:快速去重用HashSet,需要排序用TreeSet
  3. Map:常规需求HashMap,保持顺序LinkedHashMap
  4. 线程安全:高并发场景使用ConcurrentHashMap
  5. 工具类:善用Collections简化操作

建议通过以下步骤巩固学习:

  1. 编写各集合的CRUD示例
  2. 对比不同集合的性能差异
  3. 实现一个基于集合的缓存系统
  4. 阅读ArrayList/HashMap的JDK源码

掌握集合框架是Java开发的基石,合理选择数据结构能让您的程序更高效、更健壮!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小志开发

感谢您的鼓励。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值