JAVA--集合、List、链表

本文详细介绍了Java集合框架中的ArrayList和LinkedList的区别及使用场景。ArrayList基于数组实现,查询快,更改效率高,但添加和删除慢;LinkedList采用双向链表,添加删除快,但查询效率低。通过实例展示了它们的常用操作,并通过性能测试说明了在大量数据下,查询ArrayList更快,而添加和删除操作取决于插入位置。此外,还提到了集合的父类Collection及其方法,以及迭代器的使用规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

集合:

java集合是使程序能够存储和操纵元素不固定的一组数据。所有java集合类都位于java.util包中

数组和集合的区别:

数组:长度固定,存放任意同一种类型

集合:长度不固定,只能存放引用类型(如果集合中存放基本类型,要将其“装箱”成对应的基本类型包装类)

collection 是集合的父类,collection中的方法是集合中每个子类都有的

 Collection c1 = new ArrayList();创建集合
 System.out.println(c1.isEmpty());判断是否为空
 c1.add(1);基本类型先进行自动装箱,然后再向上转型
 c1.add("xxxxx");
 c1.remove("xxxxx");删除
 c1.clear();清空集合

迭代器:可以屏蔽底层数据存储的差异性
生成迭代器:Iterator it = c.iterator();
迭代器一旦创建,集合中元素不能删除和添加,否则就需要重新生成迭代器
如果在使用迭代器的过程中,需要进行删除,必须使用迭代器的remove方法

迭代器遍历完之后,想再次遍历 只能重新生成

 boolean contains(Object o) : 判断是否包含某个元素
 boolean remove(Object o) : 删除指定元素
 这两个方法,底层都会调用equals方法进行比较
 如果存储的是自定义的类型,使用contains和remove 需要覆写equals方法

List:有序可重复,存入顺序和取出顺序是一致的
ArrayList:底层是数组,查询和更改效率极高,添加和删除效率较低
LinkedList:底层是双向链表,查询效率较低,添加删除效率较高
Vector:已经过时了,底层也是数组,ArrayList是Vector的升级版
Vector 默认容量是10,扩大容量是2倍,线程安全,效率较低
ArrayList默认容量是10,扩大容量是1.5倍,非线程安全,效率较高

    ArrayList list = new ArrayList();
        ArrayList底层是Object[]数组,这就意味着只能保存引用类型
        但由于基本类型会自动装箱为包装类类型,所以Object[]数组什么都能放
        add(E e);将元素添加到列表尾部
        add(int index, E e);将元素添加到指定位置
        Arraylist覆写了toString方法,所以打印结果不是内存地址,而是里边的数据
        list.set(0, 96);替换指定位置上的元素
        list.get(i);根据索引获取对应的元素
       list.remove(int index);根据索引删除元素
        remove(Object object)删除指定元素
        要把数据封装到Integer类型中,不然就代表的是下标
        遍历方法:
        迭代器
        Iterator it =list.iterator();
        while(it.hasNext()){
            System.out.print(it.next()+" ");
        }
        forEach
        for (Object object : list) {
            System.out.print(object+" ");
        }
        for 循环
        for (int i = 0; i <list.size(); i++) {
            System.out.print(list.get(i)+" ");
        }

 LinkedList:底层是双向链表
 链表的节点由三个部分构成:
 1、添加的元素
 2、下一个节点的引用
 3、上一个节点的引用
 链表数据结构,在内存中存储也不是连续的,所以没有固定下标,因此查询效率低
 因为内存空间不是连续的,只是能找到下一个节点,因此添加和删除就变得容易了

LinkedList linkedList = new LinkedList();
        linkedList.add(99);尾部添加,成功返回true
        linkedList.push(98);头部添加
        linkedList.addLast(100);尾部添加
        linkedList.addFirst(97);头部添加
        linkedList.offerLast(101);尾部添加
        linkedList.offerFirst(96);头部添加
        没什么区别,本质都是调用linkLast和linkFirst,主要解决命名习惯问题
        System.out.print(linkedList.getLast());获取最后一个数据
        System.out.print(linkedList.getFirst());获取第一个数据
        System.out.println(linkedList.get(2));
        根据下标获取,这个下标决定的是循环的次数,模拟出来下标获取数据
        链表没有下标
        linkedList.set(4, 95);设置对应下标的数据
        linkedList.remove(1);根据索引删除元素
        linkedList.remove(new Integer(98));删除指定元素
        linkedList.poll();获取第一个元素并删除
        linkedList.pop();获取第一个元素并删除

创建ArrayList对象的时候,长度为0,可以参考ArrayList的无参构造
第一次添加元素的时候,长度设置为10,每次扩容是原来的1.5倍
实现方式:长度+长度>>1

使用ArrayList和LinkedList 分别初始化 1000W条数据
 并随机查询 和删除 测试效率问题
 ArrayList初始化完成 : 10000000 条数据耗时 2653
 LinkedList初始化完成 : 10000000 条数据耗时 7710
 ArrayList查询 6416497 对应的值为 6416497
 ArrayList查询完成 : 6416497 条数据耗时 0
 LinkeList查询 6416497 对应的值为 6416497
 LinkeList查询完成 : 6416497 条数据耗时 14
 ArrayList删除完成 : 100000 条数据耗时 219
 LinkedList删除完成 : 100000 条数据耗时 1717
 数据分析 : 查询一定是数组快,但是结果有时候显示添加和删除也是数组快
 因为数组的自动扩容机制,1.5倍增长,导致添加大量数据,才需要创建一个数组对象进行扩容,
 而删除元素后,容量并没有更改变小
 链表每次添加都需要创建新的节点对象,而删除也是需要重新指向节点引用    
 总结 : 
 插入位置的选取对LinkedList影响非常大,一直向后面添加,ArrayList会比LinkedList快,因为ArrayList有自动扩容
 对于LinkedList是添加,但是对于ArrayList来说,只是向已有空间中赋值,相当于是更改操作,而数组查询和更改效率是比较高的
 链表进行添加删除的时候,只需要引用指向即可,而数组需要数据移动位置,所以如果向前边添加数据,则链表快很多

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值