Java-集合(2)

news2024/9/26 5:14:01

List集合

List接口是Collection接口的子接口

  1. List集合类的元素是有序的(添加顺序和取出顺序是一致的)且可重复
  2. List集合类的每个元素都有对应的索引(和数组索引是一样的)

List集合的常用方法

  1. add(int index Object ele):在index索引位置插入ele元素
  2. addAll(int index Collection ele):在index索引位置将ele的所有元素添加进来
  3. get(int index ):获取在index位置的元素
  4. IndexOf(Object obj):返回obj在集合中首次出现的索引
  5. lastIndexOf(Object obj):返回obj在集合中最后一次出现的索引
  6. remove(int index):删除index索引处的元素,且返回这个元素
  7. set(int index Object ele):将index索引处的元素替换为ele
  8. subList(int fromIndex int toIndex):返回从fromIndex处到toIndex前的元素,返回为一个子集合(含头不含尾)
    方法使用演示:
public class test {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("王大");
        list.add("王三");
//        1. add(int index Object ele):在index索引位置插入ele元素
        list.add(1,"王二");
        System.out.println(list);
//        2. addAll(int index Collection ele):在index索引位置将ele的所有元素添加进来
        List list2 = new ArrayList();
        list2.add("李大");
        list2.add("王二");
        list.addAll(3,list2);
        System.out.println(list);
//        3. get(int index ):获取在index位置的元素
        System.out.println(list.get(2));
//        4. IndexOf(Object obj):返回obj在集合中首次出现的索引
        System.out.println(list.indexOf("王二"));
//        5. lastIndexOf(Object obj):返回obj在集合中最后一次出现的索引
        System.out.println(list.lastIndexOf("王二"));
//        6. remove(int index):删除index索引处的元素,且返回这个元素
        System.out.println(list.remove(2));
//        7. set(int index Object ele):将index索引处的元素替换为ele
        list.set(0,"牛大");
        System.out.println(list);
//        8. subList(int fromIndex int toIndex):返回从fromIndex处到toIndex前的元素,返回为一个子集合(含头不含尾)
        List list3 = list.subList(1,2);
        System.out.println(list3);
    }
}

输出结果:

[王大, 王二, 王三]
[王大, 王二, 王三, 李大, 王二]
王三
1
4
王三
[牛大, 王二, 李大, 王二]
[王二]

List集合练习

  1. 题目:添加10个以上的元素,在2号位置插入一个元素"好好学习"。
    获取第5个元素,删除第6个元素,修改第7个元素为“天天向上”。最后使用迭代器遍历集合,(使用ArrayList完成)
public class Work1 {
    public static void main(String[] args) {
        List list = new ArrayList();
        for (int i = 0; i < 12; i++) {
            list.add("hello"+i);
        }
        System.out.println(list);
        //2号位置插入一个元素
        list.add(1,"好好学习");
        //获取第5个元素
        System.out.println(list.get(4));
        //删除第6个元素
        list.remove(5);
        System.out.println(list);
        //修改第7个元素为“天天向上”
        list.set(6,"天天向上");
        System.out.println(list);
        //使用迭代器遍历
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            Object next =  iterator.next();
            System.out.println(next);
        }
    }
}
  1. 使用List集合实现类添加三本图书,遍历输出,打印如下效果:
    名称: 价格: 作者:
    名称: 价格: 作者:
    名称: 价格: 作者:
    按照价格排序,从低到高(使用冒泡法)
    要求使用ArrayList,LinkedList 和 Vector三种集合实现
public class Work2 {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add(new Book("三国演义",20,"罗贯中"));
        list.add(new Book("西游记",25,"吴承恩"));
        list.add(new Book("红楼梦",18,"曹雪芹"));
        list.add(new Book("java入门",30,"高斯"));
        list.add(new Book("java放弃",67,"高斯林"));
        //按照价格排序
        for (int i = 0; i < list.size(); i++) {
            for (int j = 0; j < list.size()-1-i; j++) {
                Book book1 = (Book) list.get(j);
                Book book2 = (Book) list.get(j+1);
                if (book1.price> book2.price){
                    list.set(j,book2);
                    list.set(j+1,book1);
                }
            }
        }
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
    }
}
class Book{
    String name;
    double price;
    String author;
    public Book(String name, double price, String author) {
        this.name = name;
        this.price = price;
        this.author = author;
    }
    @Override
    public String toString() {
        return "{" +
                "名称= " + name + "\t" +
                " 价格=" + price +"\t"+
                " 作者=" + author  +
                '}';
    }
}

输出结果:
{名称= 红楼梦 价格=18.0 作者=曹雪芹}
{名称= 三国演义 价格=20.0 作者=罗贯中}
{名称= 西游记 价格=25.0 作者=吴承恩}
{名称= java入门 价格=30.0 作者=高斯}
{名称= java放弃 价格=67.0 作者=高斯林}

List集合的三种遍历方式

  1. 迭代器遍历
public class test2 {
   public static void main(String[] args) {
       List list = new ArrayList();
       list.add("天天");
       list.add("向上");
       //迭代器
       Iterator iterator = list.iterator();
       while (iterator.hasNext()) {
           Object next =  iterator.next();
           System.out.println(next);
       }
   }
}
  1. 增强for遍历
       List list = new ArrayList();
       list.add("天天");
       list.add("向上");
       //增强for
       for (Object o:list) {
           System.out.println(o);
       }
  1. 普通for遍历
       List list = new ArrayList();
       list.add("天天");
       list.add("向上");
       //增强for
       for (int i = 0; i < list.size(); i++) {
           System.out.println(list.get(i));
       }

ArrayList集合实现类

ArrayList的注意事项

  1. ArrayList可以加入空元素 null,且可以加入多个
  2. ArrayList是由数组来实现数据存储的
  3. ArrayList基本等同于Vector,ArrayList线程不安全但是执行效率高,在多线程的情况下不建议使用ArrayList

ArrayList扩容机制

  1. ArrayList中维护了一个Object类型的数组elementDate
  2. 当创建ArrayList对象时,如果使用的时无参构造器,则初始elementDate容量为0,第1次添加则扩容elementDate为10,如果后续添加满了,需要再次添加,则会扩容1.5倍
  3. 如果创建ArrayList时,使用的是指定大小的构造器,则初始elementDate为指定大小,如需再次扩容,会扩容1.5倍

ArrayList无参构造创建及扩容底层源码分析

ArrayList list = new ArrayList();
for(int i = 1 ; i<=10;i++){
list.add(i);
}
for(int i = 11 ; i<=15;i++){
list.add(i);
}

可以看到上面的代码,使用ArrayList的无参构造器创建了一个对象list,然后使用for循环依次添加1~10,再次使用for循环添加11 ~15.
下面开始从源码方面分析,到底是怎么扩容的,又是怎么初始化大小的。(下列源码分析,JDK版本不同会导致源码不同,实际需自己debug分析)

  1. 无参构造器创建空数组elementDate
    在这里插入图片描述
    分析:根据前面的学习我们知道ArrayList集合类,是使用数组保存数据的。而elementDate就是这个数组,DEFAULTCAPACITY_EMPTY_ELEMENTDATA是一个默认的空数组【0】,所以此时elementDate数组就是【0】。
    2.因为是使用i进行添加,所以首先会进行一个Integer类型的装箱。
    在这里插入图片描述

3.进入add方法,然后调用ensureCapacityInternal(size + 1);方法,确认是否需要扩容:这里的size可以理解为数组当前的长度,在ensureCapacityInternal方法中会判断size + 1减elementDate.length是否大于0,如果大于0就代表当前数组已经满了,不能添加了,就会使用grow扩容。然后再添加,如果小于0就代表还可以添加,就直接添加。
在这里插入图片描述
4.进入ensureCapacityInternal(minCapacity);首先调用calculateCapacity(Object[] elementData, int minCapacity)方法传入elementDate空数组和minCapacity最小默认值 1 .然后使用if判断elementDate是不是等于默认空数组,如果是就返回 Math.max方法传入DEFAULT_CAPACITY默认最小值 10 和minCapacity 1 ,进行比较然后返回最大值,此时会返回DEFAULT_CAPACITY 的值 也就是 calculateCapacity方法会返回 10 ,(如果不是第一次添加就会返回minCapacity 的值)。
在这里插入图片描述

5.ensureCapacityInternal(minCapacity);是将calculateCapacity方法返回的值作为参数传入ensureExplicitCapacity方法,所以接下来进入ensureExplicitCapacity方法:首先modCount++模式计数加1(可以作为添加次数计数),然后使用if判断minCapacity 减elementData.length是不是大于0(10 - 0),如果是大于0就调用 grow方法把minCapacity传进去

在这里插入图片描述
6. grow(真正的扩容方法):将element的长度值给int oldCapacity 实际容量,然后将oldCapacity 实际容量+oldCapacity 实际容量>>1(位运算,除以2)也就是将oldCapacity 实际容量的1.5倍给 newCapacity 新容量。但是呢 因为是第一次,此时的oldCapacity 实际容量是0 ,0+0/2 还是等于0 .所以newCapacity 新容量也是0 ,因此下面还使用了一个if判断来防止第一次扩容失败,它使用if判断 如果newCapacity 新容量(0)减minCapacity (此时是10 )小于0的话,就表示 是第一次扩容,就将minCapacity的值给newCapacity 新容量,所以此时newCapacity 新容量的值被改成了10 ,接着又进行一个if判断,看看newCapacity 新容量是不是比最大的值还大,(这个先不分析)。最后使用Array.copy方法传入elementDate数组,和newCapacity 新容量。将原数组的数据复制且扩容大小为newCapacity 新容量的值,至此第一次数组扩容完成,elementDate数组从0变成了10

在这里插入图片描述
7.grow执行完毕返回ensureExplicitCapacity方法
在这里插入图片描述

  1. ensureExplicitCapacity方法执行完毕返回ensureCapacityInternal

在这里插入图片描述

9.ensureCapacityInternal方法执行完毕返回add方法,执行elementData[size++] = e;这里因为初始size是0且是后++,所以是在 elementData的0号下标添加传入的元素。然后size++,这样下次再进入添加的位置就会往后移动一位,不会覆盖。

add执行流程图

在这里插入图片描述
重点方法的作用:
calculateCapacity(Object[] elementData, int minCapacity):确定是否是空数组,如果是空数组就返回10 如果不是空数组就返回elementDate的长度+1

ensureExplicitCapacity(int minCapacity):根据calculateCapacity方法返回的值减去当前elementDate的长度,看够不够,如果够就直接返回add进行添加,如果不够就进入grow进行扩容,然后再返回add进行添加

grow(int minCapacity):对elementDate进行1.5倍的扩容(使用Arrays.copyOf),同时根据传入的minCapacity判断是否是第一次的空数组

ArrayList有参构造创建及扩容底层源码分析

 ArrayList list = new ArrayList(8);
        for(int i = 1 ; i<=10;i++){
            list.add(i);
        }
        for(int i = 11 ; i<=15;i++){
            list.add(i);
        }
  1. 进入有参构造器,将传入的值给initialCapactity初始容量,如果初始容量大于0就直接把elementDate数组变初始指定的大小
    如果初始容量 = 0 就还是给默认空数组后面再添加就跟无参构造创建添加一样 如果小于0就抛出异常
    在这里插入图片描述
  2. 接着还是对i 进行装箱,之后添加add方法,传入size+1(0+1),进入ensureCapacityInternal方法
    在这里插入图片描述
  3. 进入ensureCapacityInternal方法后还是首先调用ensureExplicitCapacity方法传入elementDate数组和size+1(0+1)
    在这里插入图片描述
  4. 进入ensureExplicitCapacity跟无参创建add一样:首先修改次数+1,然后用size+1(0+1)减去当前数组的容量看够不够用,如果够就直接返回到add进行添加即可
    如果不够就进行扩容,因为这里是第一次添加而需要的空间是0+1 且当前数组的长度是8,所以肯定是够的,下面直接快进到第9次添加继续debug
    在这里插入图片描述
    5.当第9次add后,进入ensureExplicitCapacity方法,此时需要的空间是9 而elementDate的长度是9 .9-9小于0,所以会进入grow进行扩容
    在这里插入图片描述
    6.进入grow,minCapacity需要容量是9 然后把elementDate的长度给新容量,接着将新容量*1.5倍,此时新容量是12
    然后if判断 新容量12 - 需要的容量9 大于0 所以不用把需要的容量给新容量。接着直接进行下面的 Arrays.copyOf()传入原数组且扩容
    在这里插入图片描述
    执行流程图:
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/140061.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软件供应链安全中:攻击面远超想象

| 软件供应链攻击3年飙升742% | 引人注目的软件供应链攻击正在上升。欧盟网络安全机构ENISA报告称&#xff0c;自2020年初以来&#xff0c;有组织的软件供应链攻击数量增加了4倍。Gartner认为&#xff0c;这一趋势将持续下去。在《软件工程领导者如何降低软件供应链安全风险》…

dubbo学习笔记1(小d课堂)

常见的dubbo项目分层&#xff1a; 搭建springbootdubbo环境 我们首先用idea创建一个maven项目&#xff1a; 我们把src删除&#xff0c;在里面创建module&#xff1a; 然后接下来我们就要去用springboot去整合dubbo。 我们可以去github上去搜索dubbo&#xff0c;会找到dubbo-s…

心理应激微反应刑事侦查应用,社交行为、情绪行为、生物行为,说谎掩饰,单向表达不分析,情绪反应管理机制,惊讶,厌恶,愤怒,恐惧,悲伤,愉悦

心理应激微反应刑事侦查应用&#xff0c;社交行为、情绪行为、生物行为&#xff0c;说谎掩饰&#xff0c;单向表达不分析&#xff0c;情绪反应管理机制&#xff0c;惊讶&#xff0c;厌恶&#xff0c;愤怒&#xff0c;恐惧&#xff0c;悲伤&#xff0c;愉悦 提示&#xff1a;系列…

【uni-app学习之日历组件】(calendar 底部可展开 折叠)

链接 效果图 代码块 <template><tmt-calendar defaultDate"2021-11-03" :point-list"[2022-03-20,2022-04-01,2022-04-02,2022-04-05]" :show"true" changeDate"changeDate"></tmt-calendar> </template>参…

【王道操作系统】4.1.1 初识文件管理概念和功能

初识文件管理概念和功能 文章目录初识文件管理概念和功能1.文件的属性2.文件内部的数据如何组织起来3.文件之间应该如何组织起来4.操作系统应该向上提供哪些功能5.从上往下看&#xff0c;文件应该如何存放在外存6.其他需要由操作系统实现的文件管理功能1.文件的属性 2.文件内部…

STM32——TIM编码器接口

文章目录一、编码器接口简介二、正交编码器三、通用定时器框图四、编码器接口基本结构五、工作模式六、实例&#xff08;均不反相&#xff09;七、实例&#xff08;TI1反相&#xff09;八、编码器接口测速电路设计关键代码一、编码器接口简介 Encoder Interface 编码器接口编码…

pycharm配置详解

配置解释器File-->setting-->Project&#xff1a;somename-->Project InterpreterPycharm下Python环境没有块注释"""something"""是文档&#xff0c;不是块注释Python中就没有块注释Pycharm版本控制配置Pycharm中的快捷键pycharm中自定…

手把手教你用springboot实现jdk文档搜索引擎

目录 项目背景 项目描述 项目整体架构 项目流程 构建索引 项目背景 搜索引擎是我们经常会用到的工具&#xff0c;例如我们熟知的百度&#xff0c;谷歌等搜索引擎。除了网络搜索引擎&#xff0c;还有很多地方也有搜索引擎的身影&#xff0c;例如视频网站的搜索框&#xff0c;…

Windows系统下使用mingw32编译curl-7.87.0办法

使用工具&#xff1a;Windows10QT5.14.2CMake (cmake-gui)curl-7.87.0 编译办法&#xff1a; 1、下载CURL源码&#xff1a;curl - Download&#xff0c;解压缩zip文件到指定路径下&#xff08;如&#xff1a;D:\QTCode\curl-7.87.0&#xff09; 2、新增环境变量&#xff0c;打…

为什么说IO密集型业务,线程数是CPU数的2倍?

I/O密集型业务&#xff0c;线程数量要设置成 CPU 的 2 倍&#xff01; 也不知道这是哪本书的坑爹理论&#xff0c;现在总有一些小青年老拿着这样的定理来说教。说的信誓旦旦&#xff0c;毋庸置疑&#xff0c;仿佛是权威的化身。讨论时把这样的理论当作前提&#xff0c;真的是受…

MySQL复制底层技术——单线程复制、DATABASE并行复制

1. 单线程复制 单线程复制是MySQL最早出现的主从复制技术&#xff0c;本节我们将对单线程复制做进一步说明。 在MySQL5.6之前的版本中&#xff0c;从库复制不支持多线程&#xff0c;所以当主库写压力稍微大一点时&#xff0c;从库就会出现复制延迟。当然&#xff0c;目前的最…

网络音频广播RtpCast软件

RtpCast是一款基于Windows平台运行的网络音频广播软件。这款RTPCast软件可以以目标分组的方式播放电脑系统声卡&#xff08;麦克风、喇叭和音频混合器&#xff09;、MP3文件列表和网络Rtp音频流等音源到终端设备。此外&#xff0c;RtpCast网络音频广播软件支持方案调度&#xf…

【区块链 | EVM】深入理解学习EVM - 深入Solidity数据位置:Calldata

深入了解Solidity数据位置 - Calldata 原文链接: https://betterprogramming.pub/solidity-tutorial-all-about-calldata-aebbe998a5fc理解Solidity中以太坊交易的 "data" 字段 这是 深入Solidity数据存储位置 系列的第三篇 今天,我们将学习 calldata 的特殊性,以…

springboot项目使用SchedulingConfigurer实现多个定时任务

目录一、引入依赖二、配置文件属性配置三、代码目录结构四、示例代码4.1、定义 定时任务基础接口4.2、定义 定时任务一&#xff08;每天几点几分执行&#xff09;4.3、定义 定时任务二&#xff08;每几分钟执行一次&#xff09;4.4、定义 定时任务注册器4.5、运行springboot项目…

欧拉系统部署NextCloud与常见部署问题解决

欧拉系统部署NextCloud与常见部署问题解决一、欧拉系统安装二、openEuler安装图形界面Ukui三、yum安装的npm包进行本地保存设置&#xff08;个人任务需要&#xff09;四、部署nextCloud4.1构建LAMP环境基础4.1.1开启httpd,防火墙端口号4.1.2开启MariaDB服务4.1.3安装并测试php4…

2023/1/4总结

今天AC了三个题目&#xff1a; 第一个题目&#xff1a;P4913 【深基16.例3】二叉树深度 (1条消息) P4913 【深基16.例3】二叉树深度_lxh0113的博客-CSDN博客 第二个题目&#xff1a;P1229 遍历问题 (1条消息) P1229 遍历问题_lxh0113的博客-CSDN博客 第三个题目&#xff1…

药品市场信息查询-药品数据库(全面)

药品市场信息包含了药品招标、药品投标、药品集采、药品销售数据&#xff08;医院、零售&#xff09;、药品海关进出口数据、药品交易&#xff08;药品license in/out&#xff09;、价格、一致性评价、政策法规、药品公司等多个方面的数据信息&#xff0c;是医药行业市场信息工…

双向循环链表的讲解及实现(图解+代码/C语言)

本次为大家分享的是双向循环链表的增删查改等系列操作。 目录 一、图解双向循环链表结构 二、分步实现 &#xff08;1&#xff09;创建并初始化 &#xff08;2&#xff09;链表元素打印 &#xff08;3&#xff09;头插和尾插 &#xff08;4&#xff09;判断链表为空 &a…

MySQL调优-MySQL索引优化实战一

目录 MySQL调优-MySQL索引优化实战一 插入数据&#xff1a; 举一个大家不容易理解的综合例子&#xff1a; 1、联合索引第一个字段用范围不会走索引 2、强制走索引 什么是回表&#xff1f;为什么要回表&#xff1f;如何进行回表&#xff1f; 但是回表具有很大的弊端&#…

NetInside网络分析帮您解决系统性能问题(二)

前言 某大学信息中心负责人表示&#xff0c;有用户反馈&#xff0c;在通过VPN访问某一IP的80端口时连接时断时续。同时信息中心给到的信息是通过VPN&#xff1a;XXX.XXX.253.5访问IP地址XXX.XXX.130.200的80端口出现访问时断时续问题。 前一文章我们分析了系统整体性能分析&a…