Java 集合框架详解:从原理到实践(附与数组对比)

前言

  在 Java 开发中,我们经常需要存储和操作一组数据,这时候 “集合” 就成了核心工具。但很多初学者会疑惑:集合和数组都是存数据的,到底有啥区别?今天就从 “数组 vs 集合” 说起,再全面拆解 Java 集合框架的CollectionMap两大体系,帮你彻底搞懂集合的用法和选型。

一、先搞清楚:集合和数组到底有啥区别?

  数组是 Java 的基础数据结构,而集合是 Java 提供的 “高级数据容器”,两者核心差异集中在灵活性、功能、存储范围三个维度,直接看对比表更清晰:

对比维度数组(Array)集合(Collection/Map)
长度特性长度固定,初始化后不能修改长度动态,可自动扩容 / 缩容
存储数据类型只能存 “同一种基本类型 / 引用类型”(如int[]String[]只能存 “引用类型”(基本类型需用包装类,如Integer),部分集合支持存不同类型(如ArrayList<Object>
功能方法仅提供 “通过索引访问” 的功能,无自带增删查改方法自带丰富方法(如add()remove()contains()sort()),无需手动实现
存储范围仅能存 “单值”(无键值对结构)支持单值(Collection)和键值对(Map)两种存储结构

举个简单例子:如果需要存 10 个学生姓名,用数组的话要先定长度String[] names = new String[10],如果后续要加第 11 个,就得重新创建数组;但用ArrayList的话,直接list.add("新同学")就行,底层会自动扩容,不用管长度。

二、集合框架核心结构:两大顶层接口

Java 集合框架的顶层结构很清晰,主要分为两大体系:

  • Collection接口:存储 “单值元素” 的集合,所有单值集合(如 List、Set)都继承自它;
  • Map接口:存储 “键值对(Key-Value)” 的集合,键唯一,值可重复,和Collection是完全独立的体系。

先看一张简化的结构示意图(帮你建立整体认知):

三、深入Collection体系:单值集合的用法

Collection是所有单值集合的父接口,定义了通用方法(如add(E e)remove(Object o)size()isEmpty()),但它是 “接口”,不能直接实例化,需要用它的子接口实现类。

1. List 接口:有序、可重复的 “动态数组”

1.1 核心特点:
  • 元素有 “索引”(和数组类似),所以有序(存储顺序 = 取出顺序);
  • 元素可重复(允许存多个相同值);
  • 常用实现类:ArrayListLinkedListVector
1.2 三大实现类对比与代码示例:
实现类底层结构优点缺点适用场景
ArrayList动态数组查询快(通过索引访问)增删慢(需移动元素)频繁查询、少增删
LinkedList双向链表增删快(只需改指针)查询慢(需遍历链表)频繁增删、少查询
Vector动态数组(线程安全)线程安全效率低(方法加锁)多线程环境(已少用,推荐CopyOnWriteArrayList

代码示例:ArrayList 基本用法

import java.util.ArrayList;
import java.util.List;

public class ListDemo {
    public static void main(String[] args) {
        // 1. 创建ArrayList实例(存储String类型)
        List<String> arrayList = new ArrayList<>();
        
        // 2. 增:添加元素
        arrayList.add("Java");
        arrayList.add("Python");
        arrayList.add("Java"); // 允许重复,正常添加
        System.out.println("添加后:" + arrayList); // 输出:[Java, Python, Java]
        
        // 3. 查:通过索引获取元素(和数组类似)
        String element = arrayList.get(1);
        System.out.println("索引1的元素:" + element); // 输出:Python
        
        // 4. 删:删除指定元素(删除第一个匹配的值)
        arrayList.remove("Java");
        System.out.println("删除后:" + arrayList); // 输出:[Python, Java]
        
        // 5. 遍历:增强for循环(推荐)
        for (String s : arrayList) {
            System.out.println("遍历元素:" + s);
        }
    }
}

2. Set 接口:无序、不可重复的 “去重集合”

2.1 核心特点:
  • 元素无序(存储顺序≠取出顺序,除非用LinkedHashSet);
  • 元素不可重复(底层通过 “哈希值 + equals ()” 保证,相同元素会被过滤);
  • 常用实现类:HashSetTreeSetLinkedHashSet
2.2 三大实现类对比与代码示例:
实现类底层结构核心特点适用场景
HashSet哈希表(数组 + 链表 / 红黑树)无序、去重、查询快只需去重,不关心顺序
TreeSet红黑树有序(按元素自然排序)、去重需要按元素排序 + 去重
LinkedHashSet哈希表 + 链表有序(保留插入顺序)、去重需要去重且保留插入顺序

代码示例:HashSet 去重与 TreeSet 排序

import java.util.HashSet;
import java.util.TreeSet;

public class SetDemo {
    public static void main(String[] args) {
        // 1. HashSet:去重+无序
        HashSet<Integer> hashSet = new HashSet<>();
        hashSet.add(3);
        hashSet.add(1);
        hashSet.add(3); // 重复元素,会被过滤
        System.out.println("HashSet:" + hashSet); // 输出:[1, 3](无序)
        
        // 2. TreeSet:排序+去重(默认自然排序:从小到大)
        TreeSet<Integer> treeSet = new TreeSet<>();
        treeSet.add(5);
        treeSet.add(2);
        treeSet.add(5); // 重复元素被过滤
        System.out.println("TreeSet:" + treeSet); // 输出:[2, 5](有序)
    }
}

3. Queue 接口:先进先出(FIFO)的 “队列”

3.1 核心特点:
  • 遵循 “先进先出”(FIFO)原则,类似排队(先到先服务);
  • 常用实现类:LinkedList(兼作队列,底层链表)、PriorityQueue(优先队列,按优先级出队)。

代码示例:LinkedList 实现队列

import java.util.LinkedList;
import java.util.Queue;

public class QueueDemo {
    public static void main(String[] args) {
        // 用LinkedList实现Queue接口
        Queue<String> queue = new LinkedList<>();
        
        // 入队:添加元素到队尾
        queue.offer("张三");
        queue.offer("李四");
        queue.offer("王五");
        System.out.println("队列:" + queue); // 输出:[张三, 李四, 王五]
        
        // 出队:移除并返回队头元素
        String head = queue.poll();
        System.out.println("出队元素:" + head); // 输出:张三
        System.out.println("出队后队列:" + queue); // 输出:[李四, 王五]
    }
}

四、深入Map体系:键值对集合的用法

MapCollection完全不同:它存储的是 “键值对(Key-Value)”,比如 “学号 - 学生姓名”“ID - 用户信息”,其中Key 必须唯一(重复会覆盖),Value 可以重复。

1. Map 核心特点与常用实现类

Map的顶层接口是java.util.Map,定义了通用方法(如put(K key, V value)get(Object key)remove(Object key)),常用实现类对比:

实现类底层结构核心特点适用场景
HashMap哈希表(数组 + 链表 / 红黑树)无序、键唯一、线程不安全、效率高单线程环境,需快速键值查询
TreeMap红黑树有序(按 Key 排序)、键唯一需要按 Key 排序的键值对场景
LinkedHashMap哈希表 + 链表有序(保留插入顺序)、键唯一需要保留键值对插入顺序
HashTable哈希表线程安全、已过时多线程环境(推荐用ConcurrentHashMap替代)

注意HashMap在 JDK1.8 后优化了底层结构 —— 当链表长度超过 8 时,会转为红黑树,提升查询效率。

2. 代码示例:HashMap 基本用法

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MapDemo {
    public static void main(String[] args) {
        // 1. 创建HashMap实例(Key:学号String,Value:姓名String)
        Map<String, String> studentMap = new HashMap<>();
        
        // 2. 存:添加键值对(Key重复会覆盖旧Value)
        studentMap.put("2023001", "张三");
        studentMap.put("2023002", "李四");
        studentMap.put("2023001", "张三(更新)"); // Key重复,覆盖旧值
        System.out.println("HashMap:" + studentMap); 
        // 输出:{2023001=张三(更新), 2023002=李四}(无序)
        
        // 3. 查:通过Key获取Value
        String name = studentMap.get("2023002");
        System.out.println("学号2023002的姓名:" + name); // 输出:李四
        
        // 4. 遍历:两种常用方式
        // 方式1:遍历所有Key,再通过Key获取Value
        Set<String> keys = studentMap.keySet();
        for (String key : keys) {
            System.out.println("Key:" + key + ",Value:" + studentMap.get(key));
        }
        
        // 方式2:直接遍历键值对(推荐,更高效)
        for (Map.Entry<String, String> entry : studentMap.entrySet()) {
            System.out.println("Key:" + entry.getKey() + ",Value:" + entry.getValue());
        }
    }
}

五、集合选型:不同场景该用哪个?

学完集合体系,最关键的是 “选对工具”,这里给大家总结一套选型思路:

  1. 需要单值存储:用Collection体系

    • 要有序、可重复、频繁查询:选ArrayList
    • 要有序、可重复、频繁增删:选LinkedList
    • 要去重、不关心顺序:选HashSet
    • 要去重、且按元素排序:选TreeSet
    • 要先进先出:选LinkedList(队列)。
  2. 需要键值对存储:用Map体系

    • 单线程、快速查询、不关心顺序:选HashMap
    • 单线程、需要按 Key 排序:选TreeMap
    • 单线程、需要保留插入顺序:选LinkedHashMap
    • 多线程、需要线程安全:选ConcurrentHashMap(不要用HashTable)。

六、总结

  Java 集合框架是开发中的 “必备工具包”,核心是Collection(单值)和Map(键值对)两大体系。和数组相比,集合更灵活(动态长度)、功能更丰富(自带增删查改),但要注意:集合只能存引用类型(基本类型需用包装类)。

  希望这篇文章能帮你理清集合的脉络,下次写代码时,再也不用纠结 “该用哪个集合” 啦!如果有疑问,欢迎在评论区交流~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值