11_Java集合框架概述

Java集合框架概述 ------ Collection与Map体系全解析

文章目录

前言

在Java开发中,数据的存储与操作是永恒的核心话题。无论是处理用户列表、缓存数据,还是构建复杂的数据结构,都离不开集合框架的支持。Java集合框架(Java Collections Framework,简称JCF)是JDK提供的一套设计精良的数据结构工具库,理解它的体系结构对于写出高效、优雅的Java代码至关重要。

集合框架的核心设计思想是接口与实现分离 ------所有的集合操作都通过接口(如List、Set、Map)来定义规范,不同的实现类(如ArrayList、LinkedList、HashMap)提供不同的底层数据结构和性能特征。这种设计让你可以在不修改调用代码的情况下切换实现类:比如从ArrayList换成LinkedList,只需修改一行new语句,其余代码保持不变。这种灵活性正是面向接口编程的最佳体现。

本文将带你从整体上把握Java集合框架的体系结构,理解Collection和Map两大接口体系,并掌握迭代器的使用方式。这篇文章是后续ArrayList/LinkedList对比和HashMap深度解析两篇文章的基础铺垫。

一、Java集合框架的体系结构

Java集合框架主要分为两大接口体系:CollectionMap 。这个划分非常清晰------Collection是"单列数据"的抽象(一条一条的元素),Map是"键值对数据"的抽象(Key→Value的映射关系)。两者是并列关系而非继承关系------Map不是Collection的子接口,这一点在面试中经常被用来制造陷阱。

  • Collection接口:存储单个元素,是List、Set、Queue的父接口
  • Map接口:存储键值对(Key-Value),与Collection接口是并列关系

整体继承关系如下:

复制代码
Collection (接口)
├── List (接口) ------ 有序、可重复
│   ├── ArrayList
│   ├── LinkedList
│   └── Vector (已基本淘汰)
├── Set (接口) ------ 无序、不可重复
│   ├── HashSet
│   ├── LinkedHashSet
│   └── TreeSet
└── Queue/Deque (接口) ------ 队列/双端队列
    ├── LinkedList
    ├── ArrayDeque
    └── PriorityQueue

Map (接口) ------ 键值对
├── HashMap
├── LinkedHashMap
├── TreeMap
└── Hashtable (已基本淘汰)

下面通过一个简单的示例来感受不同集合的特点:

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

public class CollectionOverview {
    public static void main(String[] args) {
        // List:有序可重复
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("Java");  // 允许重复
        System.out.println("List: " + list);  // [Java, Python, Java]

        // Set:无序不可重复
        Set<String> set = new HashSet<>();
        set.add("Java");
        set.add("Python");
        set.add("Java");  // 重复元素不会添加
        System.out.println("Set: " + set);  // [Java, Python] 或 [Python, Java]

        // Map:键值对
        Map<String, Integer> map = new HashMap<>();
        map.put("Java", 1995);
        map.put("Python", 1991);
        map.put("Java", 1996);  // 覆盖旧值
        System.out.println("Map: " + map);  // {Java=1996, Python=1991}
    }
}

二、Collection接口详解

Collection是List、Set、Queue的最高父接口,定义了集合操作的通用方法。

2.1 Collection核心方法

java 复制代码
public interface Collection<E> extends Iterable<E> {
    int size();                    // 返回元素个数
    boolean isEmpty();             // 判断是否为空
    boolean contains(Object o);    // 是否包含某元素
    boolean add(E e);              // 添加元素
    boolean remove(Object o);      // 移除元素
    void clear();                  // 清空集合
    Iterator<E> iterator();        // 获取迭代器
    Object[] toArray();            // 转换为数组
    // ... 还有其他方法
}

2.2 List接口

List是有序集合,可以通过索引访问元素。核心特点:有序、可重复、有索引。

java 复制代码
public class ListDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");

        // 索引访问
        System.out.println(list.get(1));        // B

        // 在指定位置插入
        list.add(1, "X");
        System.out.println(list);               // [A, X, B, C]

        // 遍历方式
        for (int i = 0; i < list.size(); i++) {
            System.out.print(list.get(i) + " "); // A X B C
        }
    }
}

2.3 Set接口

Set 不允许重复元素,主要用于去重场景。判断重复依赖**equals()hashCode()**方法。

java 复制代码
public class SetDemo {
    public static void main(String[] args) {
        Set<String> set = new HashSet<>();
        set.add("apple");
        set.add("banana");
        set.add("apple");   // 不会添加

        System.out.println(set.size());  // 2

        // TreeSet 实现排序
        Set<Integer> sortedSet = new TreeSet<>();
        sortedSet.add(5);
        sortedSet.add(1);
        sortedSet.add(3);
        System.out.println(sortedSet);   // [1, 3, 5] 自动排序
    }
}

2.4 Queue接口

Queue 模拟队列数据结构,遵循FIFO(先进先出)原则。在Java中,Queue是一个接口,LinkedList是它最常用的实现(同时实现了List和Deque)。理解Queue的API设计模式很重要,因为它体现了Java集合框架的一个设计惯例------用不同返回值处理不同错误场景

操作 抛出异常 返回特殊值
入队 add(e) offer(e) → false
出队 remove() poll() → null
查看队首 element() peek() → null

这种"双API"设计让你可以根据场景选择:如果队列为空是你预料之内的情况,用poll()返回null更优雅;如果队列应该永远非空,用remove()让异常暴露问题更合适。

java 复制代码
public class QueueDemo {
    public static void main(String[] args) {
        Queue<String> queue = new LinkedList<>();
        queue.offer("A");  // 入队
        queue.offer("B");
        queue.offer("C");

        System.out.println(queue.poll());  // A 出队并移除
        System.out.println(queue.peek());  // B 查看队首不移除
        System.out.println(queue);         // [B, C]
    }
}

三、Map接口详解

Map存储键值对(Key-Value),每个Key最多映射一个Value。

3.1 Map核心方法

java 复制代码
public interface Map<K, V> {
    V put(K key, V value);             // 添加键值对
    V get(Object key);                 // 根据Key获取Value
    V remove(Object key);              // 根据Key移除
    boolean containsKey(Object key);   // 是否包含Key
    boolean containsValue(Object value); // 是否包含Value
    Set<K> keySet();                   // 获取所有Key的Set集合
    Collection<V> values();            // 获取所有Value的Collection
    Set<Map.Entry<K, V>> entrySet();   // 获取所有键值对
    // ...
}

3.2 HashMap使用示例

java 复制代码
public class MapDemo {
    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("张三", 85);
        map.put("李四", 92);
        map.put("王五", 78);

        // 遍历方式1:通过keySet
        for (String key : map.keySet()) {
            System.out.println(key + " -> " + map.get(key));
        }

        // 遍历方式2:通过entrySet(推荐,效率更高)
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + " -> " + entry.getValue());
        }

        // 遍历方式3:forEach(Java 8+)
        map.forEach((key, value) -> 
            System.out.println(key + " -> " + value));
    }
}

四、迭代器详解

Iterator 是遍历集合的统一方式,所有Collection的子类都可以通过iterator()获取迭代器。

4.1 迭代器的三个核心方法

java 复制代码
public class IteratorDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("C++");

        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            String element = iterator.next();
            System.out.println(element);
        }
    }
}
  • hasNext():判断是否还有下一个元素
  • next():返回当前元素并将指针后移
  • remove():移除上次next()返回的元素

4.2 迭代过程中安全删除元素

遍历集合时,如果直接用集合的remove()方法删除元素,会抛出ConcurrentModificationException 。这是因为集合内部有一个modCount计数器,每次结构性修改都会自增,而迭代器在创建时会记录当时的modCount值,每次next()时检查是否一致。如果直接用集合的remove()(会修改modCount),迭代器的检查就会失败------这是一种**fail-fast(快速失败)**机制,用于尽早暴露并发修改问题。

正确做法是使用迭代器的remove()方法,它会同步更新自己的expectedModCount。JDK 8还提供了更简洁的removeIf()方法,内部也是基于迭代器实现。

java 复制代码
public class SafeRemoveDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("Java");
        list.add("Python");
        list.add("C++");

        // 错误做法:会抛出ConcurrentModificationException
        // for (String s : list) {
        //     if ("Python".equals(s)) {
        //         list.remove(s);  // 危险!
        //     }
        // }

        // 正确做法:使用迭代器的remove()
        Iterator<String> it = list.iterator();
        while (it.hasNext()) {
            String s = it.next();
            if ("Python".equals(s)) {
                it.remove();  // 安全删除
            }
        }
        System.out.println(list);  // [Java, C++]
    }
}

4.3 增强for循环的本质

增强for循环(foreach)实际上是迭代器的语法糖,编译后等价于使用Iterator遍历:

java 复制代码
// 源码写法
for (String s : list) {
    System.out.println(s);
}

// 编译后等价于
for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
    String s = it.next();
    System.out.println(s);
}

五、迭代器模式的设计思想

迭代器模式的精髓在于将遍历行为从集合本身分离出来。这样做的好处是:

  1. 解耦:遍历算法与集合的实现分离
  2. 统一接口:无论底层是数组还是链表,遍历方式都一样
  3. 封装内部结构:调用者无需知道集合的内部实现

设计模式实践

java 复制代码
// 使用ListIterator实现双向遍历(仅List实现支持)
public class ListIteratorDemo {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("一");
        list.add("二");
        list.add("三");

        ListIterator<String> listIterator = list.listIterator();

        // 正向遍历
        while (listIterator.hasNext()) {
            System.out.print(listIterator.next() + " ");  // 一 二 三
        }
        System.out.println();

        // 反向遍历
        while (listIterator.hasPrevious()) {
            System.out.print(listIterator.previous() + " ");  // 三 二 一
        }
    }
}

六、集合的选择策略

在实际开发中,选择合适的集合类型非常重要,这直接影响程序的性能和可读性。以下是一些选择建议:

需求场景 推荐集合
需要快速随机访问 ArrayList
频繁插入删除 LinkedList
需要去重 HashSet
需要排序 TreeSet / TreeMap
需要键值对 HashMap
线程安全场景 ConcurrentHashMap / CopyOnWriteArrayList
按插入顺序遍历 LinkedHashMap / LinkedHashSet

总结

本文介绍了Java集合框架的整体架构,涵盖了Collection和Map两大接口体系,以及迭代器的使用方式。集合框架是Java中最常用的工具库,可以说任何Java项目都离不开它。以下是本文的核心收获:

  • Collection体系:List(有序可重复,适合按索引操作)、Set(无序不可重复,适合去重)、Queue(FIFO队列,适合任务调度)三大子接口各有专攻
  • Map体系:键值对存储,HashMap是最常用的实现,TreeMap适合排序场景,LinkedHashMap适合按插入顺序遍历
  • Iterator迭代器:统一的遍历接口,将遍历逻辑与底层数据结构解耦。增强for循环本质是迭代器的语法糖
  • fail-fast机制ConcurrentModificationException是集合的"安全阀",防止在遍历过程中被意外修改导致数据不一致

掌握这些基础知识后,在后续文章中我们将深入探讨ArrayList和LinkedList的底层原理、HashMap的哈希表实现、以及多线程环境下的并发集合等高级话题。集合框架的真正功力体现在选型能力上------同样是存储100万条数据,选ArrayList还是LinkedList?选HashMap还是TreeMap?这取决于你对底层数据结构的理解深度。

Java集合框架的设计充分体现了接口与实现分离、抽象层次分明的设计思想。理解这套框架,对于一个Java开发者来说不仅是面试的必备知识,更是写出高质量代码的基础。

✅ 亮点总结

  • Collection与Map两大体系划分:Collection存储单列数据(List/Set/Queue),Map存储键值对(HashMap/TreeMap),用一张全景图理清所有集合类的归属
  • Iterator迭代器模式的优雅设计 :将遍历行为与底层数据结构解耦,无论ArrayList数组还是LinkedList链表,hasNext()/next()接口完全统一
  • ListIterator的双向遍历能力 :相比普通Iterator只能"前进",ListIterator支持"后退"(hasPrevious()/previous()),适合需要双向操作的场景
  • 集合选择速查表:一张表格将"需随机访问→ArrayList"、"需去重→HashSet"、"需排序→TreeMap"等常见场景一一对应,减少选型犹豫
  • 接口与实现分离的设计思想List<String> list = new ArrayList<>()------声明用接口,实现选具体类,这是面向接口编程的经典实践

适用场景

  • 全局搜索项目中所有使用List的地方,检查是否选择了正确的实现类(是否滥用LinkedList或漏用HashSet去重)
  • 处理从数据库或API返回的批量数据时,根据后续操作(遍历/随机访问/去重/排序)选择合适的集合类型
  • 重构代码时,将for (int i = 0; i < list.size(); i++)统一替换为增强for循环或迭代器,提升代码可读性

扩展方向

  • ArrayList vs LinkedList深度对比 :理解两者底层数据结构和时间复杂度差异,做出最优选型,推荐阅读 12_ArrayList与LinkedList深度对比
  • HashMap底层原理 :数组+链表+红黑树的哈希表实现,JDK 1.7到1.8的演进故事,推荐阅读 13_HashMap底层原理详解
  • 并发集合ConcurrentHashMap的分段锁机制、CopyOnWriteArrayList的写时复制策略,理解多线程环境下的集合安全方案

下一篇:12_ArrayList与LinkedList深度对比

相关推荐
小谢小哥1 小时前
64-依赖冲突解决详解
java·后端·架构
好好风格1 小时前
微软这个 14 万星工具,把 PDF、PPT、Excel 都变成大模型爱读的 Markdown
人工智能·python·开源
阿杰AJie1 小时前
ExcelUtils样式相关工具
java·后端
jsl_jsl_jsl1 小时前
☕ Java 高并发进阶(三):Java 锁体系全景解析——从 Synchronized 到 AQS 高阶锁
java
小糖学代码1 小时前
机器学习:1.机器学习基本概念
人工智能·python·机器学习
love_muming1 小时前
从 ArrayList 到 LinkedList:Java 集合中数组与链表的深度对比
java·数据结构·链表
甄心爱学习1 小时前
【项目实训】法律文书智能摘要系统7
git·python
荣码1 小时前
Java后端用LangChain搭大模型应用,我踩了5个坑
java