Java集合框架-Collection

plaintext 复制代码
Java集合框架
├── Collection (接口):单列
│   ├── List (接口):有序、可重复、有索引
│   │   ├── ArrayList (实现类)
│   │   ├── LinkedList (实现类)
│   │   └── Vector (实现类,线程安全,已基本淘汰)
│   ├── Set (接口):无序、不可重复、无索引
│   │   ├── HashSet (实现类)
│   │   │   └── LinkedHashSet (子类,有序)
│   │   └── TreeSet (实现类,可排序,默认升序)
│   └── Queue (接口):队列(先进先出FIFO)
│       └── LinkedList (同时实现Queue,常用)
└── Map (接口)::双列,键值对,键唯一,值可重复
    ├── HashMap (实现类)
    │   └── LinkedHashMap (子类,有序)
    ├── TreeMap (实现类,可排序)
    └── Hashtable (实现类,线程安全,已基本淘汰)

Collection

遍历:1. iterator 2. 增强for循环 3. Lambda

关键:1. 增强for循环在都会编译成iterator迭代器;2. Lambda:forEach是语法糖底层还是调用iterator迭代器;3.集合存储的都是对象,基本类型会自动装箱;4. iterator遍历中不能删除新增

拓展:1. 解决 iterator遍历删除问题,匹配删除时手动i--,iterator的remove封装了;2. Iterator 遍历的核心是 "快速失败" 原则:遍历过程中,若集合的结构(元素个数)被修改(新增 / 删除),且修改操作不是通过迭代器自身的方法完成,迭代器会立即检测到并抛出异常,避免遍历出现不可预期的结果,底层逻辑是集合内部维护一个modCount(修改次数)变量,迭代器创建时会记录这个值(expectedModCount)。遍历中每次调用next()都会校验modCount == expectedModCount,不相等则抛异常;3. ListIterator是 Iterator 的子接口(仅 List 集合支持),它的add()方法会同步更新expectedModCount;4. 增强for循环和Lambda在操作遍历删除都只是集合的remove,而不是iterator封装的remove,可能造成错误。

List

ArrayList

实现原理:1. 存储:数组(Object[])- 连续存储;2. 扩容:存储一个对象,对象能有数组elementData和size代表当前存储下标和数组已填充大小,当填入一个数据时数组elementData为10初始大小,当存满时,会扩容1.5倍,如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际为准;

遍历:1. for循环

关键:1. ArrayList转换为数组 toArray()返回Object[];2. ArrayList转换为指定类型数组 toArray(new String[]) ;3. addAll () 执行的是浅拷贝(浅复制),而非深拷贝。

规范:1. List list = new ArrayList<>(); 多态写法

应用场景:1. ArrayList适合:根据索引l查询数据比如根据随机索引取数据(高效)!或者数据量不是很大时;2. ArrayList不适合: 数据量大的同时又要频繁的进行增删操作!

LinkedList

实现原理:双链表,

特点:查询慢(比较单链表快,可以通过判定索引靠前还是靠后判定从头遍历还是从尾遍历),增删相对较快,但对首尾元素进行增删改查的速度是极快的。

应用场景:1. 栈、堆;

Set

注意:Set要用到的常用方法,基本上就是collection提供的!!自己几乎没有额外新增一些常用功能!

HashSet

实现原理:存储:基于哈希表实现。哈希表是一种增删改查数据,性能都较好的数据结构。操作:1. 创建一个默认长度16的数组,默认加载因子为0.75,数组名table

  1. 使用元素的哈希值对数组的长度求余计算出应存入的位置
  2. 判断当前位置是否为null,如果是null直接存入(去重,数组和链表或红黑树都会判断)
  3. 如果不为null,表示有元素,则调用eguals方法比较
    相等,则不存;不相等,则存入数组
  • JDK 8之前,新元素存入数组,占老元素位置,老元素挂下面
  • JDK8开始之后,当链表长度超过8,且数组长度>=64时,新元素直接挂在老元素下面

去重:哈希函数计算位置后通过hasCode判断在数组中是否重复,不重复,在逐一equal比较链表或红黑树节点,通过对象的重写hasCode和equal

拓展:树:二叉查找树(二叉排序树)、平衡二叉树、红黑树(自平衡的二叉树);关系:哈希表 :是一种通用的数据结构(数组 + 链表 / 红黑树),目标是通过哈希函数实现 O (1) 级别的增删查;HashMap :Java 中哈希表的具体实现类,底层是 "数组(桶)+ 链表 + 红黑树"(JDK 1.8+);HashSet:是 HashMap 的 "包装类",通过复用 HashMap 的键(Key)实现去重,值(Value)是一个固定的空对象。

LinkedHashSet

实现原理:排序:每个元素都额外的多了一个双链表的机制记录它前后元素的位置,当插入第一个元素确定位于数组的位置,此时标记首节点变量和标记尾节点变量都指向第一个元素,当插入第二个元素时,将标记尾节点变量地址和新插入地址建立双向,然后将标记尾节点变量更新地址

TreeSet

实现原理:基于红黑树实现

排序规则:默认升序排序,按照元素的大小,由小到大排序,自定义排序规则:方式一:让自定义的类(如学生类)实现comparable接口,重写里面的compareTo方法来指定比较规则。方式二:通过调用TreeSet集合有参数构造器,可以设置comparator对象(比较器对象,用于指定比较规则。public TreeSet(Comparator<? super E> comparator)如果两种排序都存在,TreeSet就近选择自已自带的比较器对象进行排序(即方法二);去重:根据排序规则比较的值去重

拓展:红黑树 :一种自平衡的二叉查找树(BST),保证任意节点的左右子树高度差不超过两倍,查询 / 增删时间复杂度稳定在 O(logn)TreeMap :Java 中红黑树的具体实现类,存储键值对,且键会自动排序(自然排序 / 自定义排序);TreeSet:TreeMap 的 "包装类",将元素作为 TreeMap 的 Key,Value 是固定空对象,复用TreeMap 的排序 + 去重逻辑。

应用场景汇总

1、如果希望记住元素的添加顺序,需要存储重复的元素,又要频繁的根据索引查询数据?

用ArrayList集合(有序、可重复、有索引l),底层基于数组的。(常用)

2、如果希望记住元素的添加顺序,且增删首尾数据的情况较多?

用LinkedList集合(有序、可重复、有索引l),底层基于双链表实现的。

3。如果不在意元素顺序,也没有重复元素需要存储,只希望增删改查都快?

用HashSet集合(无序,不重复,无索引),底层基于哈希表实现的。(常用)

4.如果希望记住元素的添加顺序,也没有重复元素需要存储,且希望增删改查都快?

用LinkedHashSet集合(有序,不重复,无索引l),底层基于哈希表和双链表。

5.如果要对元素进行排序,也没有重复元素需要存储?且希望增删改查都快?

用TreeSet集合,基于红黑树实现。

iterator迭代器

原理:迭代器的本质是为每个集合实例创建一个 "专属遍历对象" ,这个对象持有当前遍历的位置(状态),并封装了 "如何遍历当前集合" 的逻辑(不同集合的遍历逻辑不同,但对外接口统一)。

ArrayList的迭代器(内部类Itr)为例,看其核心原理:

java 复制代码
public class ArrayList<E> {
    private Object[] elementData; // 底层数组
    private int size; // 元素个数
    private int modCount; // 集合修改次数(快速失败用)

    // ArrayList的内部迭代器实现
    private class Itr implements Iterator<E> {
        int cursor; // 【遍历状态】下一个要返回的元素的索引(初始为0)
        int lastRet = -1; // 【遍历状态】上一个返回的元素的索引(初始为-1)
        int expectedModCount = modCount; // 记录迭代器创建时的集合修改次数

        // 1. 判断是否有下一个元素:游标没到size则有
        @Override
        public boolean hasNext() {
            return cursor != size;
        }

        // 2. 获取下一个元素:移动游标,返回元素
        @Override
        public E next() {
            // 快速失败校验:集合修改次数变化则抛异常
            checkForComodification();
            int i = cursor;
            if (i >= size) throw new NoSuchElementException();
            Object[] elementData = ArrayList.this.elementData;
            if (i >= elementData.length) throw new ConcurrentModificationException();
            cursor = i + 1; // 游标后移
            return (E) elementData[lastRet = i]; // 记录上一个元素的索引
        }

        // 3. 安全删除:删除上一个返回的元素
        @Override
        public void remove() {
            if (lastRet < 0) throw new IllegalStateException();
            checkForComodification(); // 快速失败校验
            try {
                ArrayList.this.remove(lastRet); // 调用集合的删除方法
                cursor = lastRet; // 游标回退(避免跳过元素)
                lastRet = -1; // 重置lastRet
                expectedModCount = modCount; // 同步修改次数
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }

        // 快速失败校验:集合修改次数≠迭代器记录的次数则抛异常
        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
    }
}

Collections工具类

  • public static boolean addAll(collection<? super T> c, T...elements)为集合批量添加0个或多个元素
  • public static void shuffle(List<?> list): 打乱List集合中的元素
  • public static void sort(List list):对List集合中的元素进行升序排序。
  • public static void sort(List list, Comparator<? super T> c)
    对List集合中元素,按照比较器对象指定的规则进行排序,方式一:让自定义的类(如学生类)实现comparable接口,重写里面的compareTo方法来指定比较规则。方式二:通过有参数方法,可以传入comparator对象
相关推荐
雾岛听蓝1 小时前
AVL树实现
开发语言·c++
悟空码字1 小时前
Spring Cloud 集成 Nacos,全面的配置中心与服务发现解决方案
java·nacos·springcloud·编程技术·后端开发
小冷coding1 小时前
【Java】基于Java的线上贷款分发业务技术栈设计方案
java·开发语言
星火开发设计1 小时前
循环结构进阶:while 与 do-while 循环的适用场景
java·开发语言·数据结构·学习·知识·循环
重生之绝世牛码1 小时前
Linux软件安装 —— JDK安装
java·大数据·linux·运维·jdk
程序媛徐师姐1 小时前
Java基于微信小程序的农产品自主供销系统,附源码+文档说明
java·微信小程序·农产品自主供销·农产品自主供销系统·农产品自主供销小程序·java农产品自主供销小程序·农产品自主供销微信小程序
青衫码上行1 小时前
Maven高级:分模块、聚合继承、多环境配置与私服搭建
java·学习·maven
无名-CODING1 小时前
Spring Bean生命周期详解:从入门到精通
java·后端·spring
郝学胜-神的一滴2 小时前
Qt自定义TabWidget:实现左侧标签与水平文本布局
开发语言·c++·qt·程序人生