当前位置: 首页 > news >正文

《Java集合框架核心解析》

Java 集合框架是 Java 编程中存储和操作数据的核心工具,为我们提供了丰富的数据结构实现.本文将围绕Collection接口下的List、SetQueue 三大分支,深入解析各核心实现类的特性、数据结构及适用场景,帮助大家更好地理解和运用 Java 集合。

一、List 接口(有序可重复) 

(一)ArrayList 

ArrayList 基于动态数组存储元素,是日常开发中最常用的 List 实现。

  • 底层存储
    transient Object[] elementData; // 存储元素的数组,transient修饰避免无意义序列化
    private int size; // 集合中元素的实际个数
    
  • 初始化与扩容
    • 初始化时
      • 无参构造时elementData默认是长度为 0 的空数组,添加第一个元素时,数组扩容为 10
      • 有参构造可指定初始容量
    • 容量不足时,扩容逻辑(grow方法):

      private void grow(int minCapacity) {int oldCapacity = elementData.length;int newCapacity = oldCapacity + (oldCapacity >> 1); // 新容量为原容量的1.5倍if (newCapacity - minCapacity < 0)newCapacity = minCapacity;elementData = Arrays.copyOf(elementData, newCapacity); // 数组拷贝扩容
      }
      
  • 特点与适用场景
    有序、允许重复元素。基于数组的结构使其随机访问,但插入、删除元素效率低,适合查找和遍历。

(二)LinkedList

LinkedList 基于双向链表实现,同时实现了Queue接口,兼具列表和队列的特性。

  • 链表节点结构

    private static class Node<E> {E item;Node<E> next;Node<E> prev;Node(Node<E> prev, E element, Node<E> next) {this.item = element;this.next = next;this.prev = prev;}
    }
    

    每个节点包含元素值item、前驱指针prev和后继指针next,通过指针连接形成双向链表。
  • 增删操作
    添加或删除元素时,只需调整节点的prev和next指针,无需像数组那样移动元素。

    public boolean add(E e) {linkLast(e);return true;
    }
    void linkLast(E e) {final Node<E> l = last;final Node<E> newNode = new Node<>(l, e, null);last = newNode;if (l == null)first = newNode;elsel.next = newNode;size++;
    }
    
  • 特点与适用场景
    有序、允许重复元素。插入、删除元素效率高,但随机访问效率低,适合增删操作频繁的场景。

(三)Vector

Vector是早期 Java 提供的动态数组实现,与ArrayList类似,但具备线程安全特性

  • 线程安全保证
    大部分方法都用synchronized 修饰,例如add方法:

    public synchronized boolean add(E e) {modCount++;ensureCapacityHelper(elementCount + 1);elementData[elementCount++] = e;return true;
    }
    
  • 扩容机制
    public class CustomArrayList {// 存储元素的数组private Object[] elementData;// 集合中元素的实际个数private int size;// 自定义增长量private int capacityIncrement;// 无参构造方法,默认初始容量为 10,自定义增长量为 0(即默认按原容量的 2 倍扩容)public CustomArrayList() {this(10, 0);}// 有参构造方法,按照指定容量和自定义增长量创建数组public CustomArrayList(int initialCapacity, int capacityIncrement) {if (initialCapacity < 0) {throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);}this.elementData = new Object[initialCapacity];this.capacityIncrement = capacityIncrement;}// 添加元素方法public boolean add(Object e) {// 检查容量是否足够,不够则扩容ensureCapacityHelper(size + 1);elementData[size++] = e;return true;}// 确保容量足够的辅助方法private void ensureCapacityHelper(int minCapacity) {if (minCapacity > elementData.length) {// 执行扩容grow(minCapacity);}}// 扩容方法private void grow(int minCapacity) {int oldCapacity = elementData.length;// 计算新容量:如果自定义增长量大于 0,就用原容量 + 自定义增长量;否则用原容量的 2 倍int newCapacity = oldCapacity + ((capacityIncrement > 0) ? capacityIncrement : oldCapacity);// 如果计算后的新容量还是小于最小需要的容量,就把最小需要的容量作为新容量if (newCapacity - minCapacity < 0) {newCapacity = minCapacity;}// 数组拷贝,将原数组元素复制到新数组elementData = java.util.Arrays.copyOf(elementData, newCapacity);}// 获取元素方法public Object get(int index) {if (index < 0 || index >= size) {throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);}return elementData[index];}// 获取元素个数方法public int size() {return size;}public static void main(String[] args) {// 示例 1:使用无参构造,默认初始容量 10,扩容为原容量的 2 倍CustomArrayList list1 = new CustomArrayList();for (int i = 0; i < 20; i++) {list1.add("Element " + i);}System.out.println("list1 size: " + list1.size());// 示例 2:使用有参构造,初始容量 5,自定义增长量 3,扩容为原容量 + 3CustomArrayList list2 = new CustomArrayList(5, 3);for (int i = 0; i < 15; i++) {list2.add("Item " + i);}System.out.println("list2 size: " + list2.size());}
    } 
  1. 初始化
    • 无参构造方法CustomArrayList()调用有参构造,默认初始容量为 10自定义增长量capacityIncrement为 0
    • 有参构造方法CustomArrayList(int initialCapacity, int capacityIncrement)按照指定的初始容量和自定义增长量创建存储元素的数组 elementData。
  2. 扩容逻辑
    • 在grow方法中,首先获取原数组容量oldCapacity
    • 然后根据自定义增长量capacityIncrement计算新容量newCapacity,如果capacityIncrement > 0,新容量为oldCapacity + capacityIncrement;否则新容量为oldCapacity * 2
    • 最后使用Arrays.copyOf方法将原数组元素复制到新数组,完成扩容。
  • 特点与适用场景
    有序、允许重复元素且线程安全,但由于同步锁的存在,性能比 ArrayList 低。在单线程环境下推荐ArrayList,多线程且需安全时可考虑Vector。 

(四)Stack

Stack是Vector的子类,基于 栈(FILO,先进后出)数据结构。

  • 底层存储
  • public E push(E item) {addElement(item); // 调用Vector的addElement方法,添加到尾部return item;
    }
    public synchronized E pop() {E       obj;int     len = size();obj = peek();removeElementAt(len - 1); // 移除尾部元素return obj;
    }
    public synchronized E peek() {int     len = size();if (len == 0)throw new EmptyStackException();return elementAt(len - 1); // 获取尾部元素
    }
    
  • 特点与适用场景
    遵循 FILO 原则,适用于需要 “后进先出” 逻辑的场景(如表达式求值、括号匹配等)。

二、Set 接口(无序不重复

(一)HashSet(基于 HashMap 的去重实现)

         HashSet底层依赖HashMap,利用哈希表保证元素不重复。

  • private transient HashMap<E,Object> map;
    private static final Object PRESENT = new Object(); // 所有值都指向这个空对象
    

    HashSet将元素作为HashMap的键,值统一为PRESENT (节省空间)。
  • 添加元素

    public boolean add(E e) {return map.put(e, PRESENT) == null; // HashMap的put返回旧值,若为null说明是新元素
    }
    

    利用HashMap键的唯一性,实现Set的 “不重复” 特性。
  • 特点与适用场景
    无序、不允许重复元素,查询效率高,适合只需去重且不关心顺序的场景。

(二)LinkedHashSet(有序的 HashSet)

LinkedHashSet继承自HashSet,内部使用LinkedHashMap,保证元素 “插入有序”

  • 有序性保证
    构造时传入LinkedHashSet实例

    public LinkedHashSet() {super(new LinkedHashMap<>());
    }
    

    LinkedHashMap通过双向链表记录元素的插入顺序,因此LinkedHashSet能保证元素遍历顺序与插入顺序一致。
  • 特点与适用场景
    兼具HashSet的去重、高效查询特性,又能保证插入顺序,适合需要去重且关注元素添加顺序的场景。

(三)TreeSet(有序的红黑树实现)

TreeSet基于TreeMap,利用红黑树实现元素的 “自动排序”

  • 底层关联与排序

    private transient NavigableMap<E,Object> m;
    public TreeSet() {this(new TreeMap<E,Object>());
    }
    

    TreeMap是基于红黑树的有序映射,要求键实现Comparable接口或构造时传入Comparator,因此TreeSet中的元素会按照自然顺序或自定义比较器顺序排列
  • 添加元素
    依赖TreeMap的put方法,红黑树会自动调整结构以保持有序。
  • 特点与适用场景
    自动排序(有序)、不允许重复元素,适合需要有序去重的场景(如排行榜、范围查询等)。

三、Queue 接口(先进先出的队列)

(一)LinkedList(双向链表实现的队列)

LinkedList实现了Queue 接口,基于双向链表提供队列操作

  • 队列方法

    public boolean offer(E e) {return add(e); // 调用List的add方法,添加到尾部
    }
    public E poll() {final Node<E> f = first;return (f == null) ? null : unlinkFirst(f); // 移除并返回头部元素
    }
    public E peek() {final Node<E> f = first;return (f == null) ? null : f.item; // 返回头部元素(不删除)
    }
    
  • 特点与适用场景
    遵循 FIFO(先进先出)原则,适合作为任务队列等场景的基础结构。

(二)PriorityQueue(优先级队列)

PriorityQueue基于二叉堆实现,元素按优先级出队(非严格 FIFO)

  • 底层存储与排序

    transient Object[] queue; // 用数组存储堆元素
    private final Comparator<? super E> comparator; // 比较器,决定优先级
    

    通过siftUp(上浮)和siftDown(下沉)操作维护堆结构,保证每次出队的是 “优先级最高” 的元素。
  • 出队操作

    public E poll() {if (size == 0)return null;int s = --size;modCount++;E result = (E) queue[0];E x = (E) queue[s];queue[s] = null;if (s != 0)siftDown(0, x); // 下沉调整堆return result;
    }
    
  • 特点与适用场景
    元素按优先级(自然顺序或自定义比较器)排列,适用于 “优先级调度” 场景(如高优先级任务先执行)。

四、单列集合总结 

集合类数据结构有序性重复性线程安全适用场景
ArrayList动态数组插入有序允许读多写少、随机访问频繁
LinkedList双向链表插入有序允许增删频繁、随机访问少
Vector动态数组插入有序允许多线程安全且需动态数组场景
Stack栈(基于 Vector)FILO允许后进先出逻辑(如表达式求值)
HashSet哈希表无序不允许去重、不关心顺序
LinkedHashSet链表 + 哈希表插入有序不允许去重且需插入顺序
TreeSet红黑树排序有序不允许有序去重(如排行榜)
LinkedList(Queue)双向链表FIFO允许先进先出队列
PriorityQueue二叉堆优先级有序允许优先级调度(如任务队列)


文章转载自:

http://zbo6nxrV.khxyx.cn
http://kbz4qKmm.khxyx.cn
http://Ne50E0us.khxyx.cn
http://nWPVYgDo.khxyx.cn
http://yK2iyOMt.khxyx.cn
http://JibCzIgq.khxyx.cn
http://pl0JImdZ.khxyx.cn
http://tMIYK2xq.khxyx.cn
http://U1ZUGIMh.khxyx.cn
http://hJSFSYiw.khxyx.cn
http://DX6FiZvl.khxyx.cn
http://bn9E1W76.khxyx.cn
http://12QGSo5I.khxyx.cn
http://7Hf06HHr.khxyx.cn
http://hMPHMFGw.khxyx.cn
http://0L9etMLu.khxyx.cn
http://rUK2LoI1.khxyx.cn
http://H4EryeAV.khxyx.cn
http://lGd6EApL.khxyx.cn
http://JeJ74iuN.khxyx.cn
http://zYdUddHH.khxyx.cn
http://Lie5p5yC.khxyx.cn
http://pSLpn9Up.khxyx.cn
http://i8ftAgg3.khxyx.cn
http://9FCrxlQL.khxyx.cn
http://CQpKdJiI.khxyx.cn
http://DcByBgh7.khxyx.cn
http://RqLmNyx0.khxyx.cn
http://CFkuuUQf.khxyx.cn
http://mQ4T5KPO.khxyx.cn
http://www.dtcms.com/a/386621.html

相关文章:

  • 二维码生成器
  • OSI七层模型
  • 【原创·极简新视角剖析】【组局域网】设备在同一局域网的2个条件
  • 第8课:高级检索技术:HyDE与RAG-Fusion原理与DeepSeek实战
  • Windows 命令行:路径的概念,绝对路径
  • 异常检测在网络安全中的应用
  • 【ubuntu】ubuntu 22.04 虚拟机中扩容操作
  • 【数值分析】05-绪论-章节课后1-7习题及答案
  • Java NIO 核心机制与应用
  • Roo Code 诊断集成功能:智能识别与修复代码问题
  • ANA Pay不再接受海外信用卡储值 日eShop生路再断一条
  • 一阶惯性环节的迭代公式
  • AWS 热门服务(2025 年版)
  • 拷打字节算法面试官之-深入c语言递归算法
  • Vehiclehal的VehicleService.cpp
  • 【传奇开心果系列】基于Flet框架实现的允许调整大小的开关自定义组件customswitch示例模板特色和实现原理深度解析
  • 八股整理xdsm
  • SpringBoot 配置文件详解:从基础语法到实战应用
  • lesson62:JavaScript对象进化:ES2025新特性深度解析与实战指南
  • ARM C1-Premium core简介
  • 机器学习-深度神经网络架构
  • godot+c#实现玩家动画
  • 【Axure高保真原型】标签树分类查询案例
  • 系统架构设计(一)
  • RK3568下QT实简易文件浏览器
  • 设备综合效率(OEE)讲解与计算案例
  • STM32G4 电流环闭环(二) 霍尔有感运行
  • git-gui --批量处理文件
  • 【代码随想录day 28】 力扣 55.跳跃游戏
  • Python Flask 项目实战