Java小白一文讲清Java中集合相关的知识点(二)

news2024/11/15 11:37:05

List

List接口和常用方法

基本介绍

List接口是Collection接口的子接口

  • List集合类中的元素有序–即添加顺序和取出顺序一致、且可重复
public class Journey {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("kerwin");
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("kerwin");
        list.add(true);
        System.out.println("list="+list);
    }
}
//输出
list=[kerwin, A, B, C, kerwin, true]
  • List集合中的每一个元素都有其对应的顺序索引,即支持索引
@SuppressWarnings({"all"})
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("kerwin");
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("kerwin");
        list.add(true);
        System.out.println("list="+list);

        System.out.println(list.get(2));//B
    }
  • List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素
  • List接口的实现类有ArrayList 、 LinkedList 、Vector
常用方法

在这里插入图片描述

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

public class Journey {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("kerwin");
        list.add("A");
        list.add(true);
        list.add(0,"Blue");
        System.out.println("list="+list);//输出如下
//        list=[Blue, kerwin, A, true]

        List list2 = new ArrayList();
        list2.add(false);
        list2.add(1110);
        list2.addAll(0,list);
        System.out.println("list2="+list2);//输出如下
//        list2=[Blue, kerwin, A, true, false, 1110]

        System.out.println(list.get(0));//Blue
        System.out.println(list2.get(4));//false

        System.out.println(list.indexOf("Blue"));//0

        list.add("kerwin");
        System.out.println("第二次新加了个元素kerwin后的list="+list);//输出如下
//        第二次新加了个元素kerwin后的list=[Blue, kerwin, A, true, kerwin]

        System.out.println(list.lastIndexOf("kerwin"));//4
        System.out.println(list.indexOf("kerwin"));//1

        list.remove("Blue");
        System.out.println("移除了一个元素后的list="+list);
//        移除了一个元素后的list=[kerwin, A, true, kerwin]

        System.out.println(list.set(0, "A"));//设置指定的index 0 位置处的元素为 A,输出 kerwin
        //如果.set(index,ele)中的index不存在则会报数组越界异常,所以index必须存在才行
        System.out.println(list);//此时输出如下
//        [A, A, true, kerwin]

        System.out.println(list.subList(1, 3));//输入如下,取[1,3)区间的元素
//          [A, true]

    }
}

练习
在这里插入图片描述

public class Journey {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("kerwin");
        list.add(1110);
        list.add(true);
        list.add("hello");
        list.add(1110);
        list.add(3.14);
        System.out.println("list="+list);
//        list=[kerwin, 1110, true, hello, 1110, 3.14]

        //在3号位插入hsp,注意3号位是指第三个元素,其索引是2,list中的索引是从0开始的哈
        list.add(2,"hsp");
        System.out.println("添加了hsp后的list="+list);
//        添加了hsp后的list=[kerwin, 1110, hsp, true, hello, 1110, 3.14]

        //获得第5个元素
        System.out.println(list.get(4));//hello

        //删除第6个元素
        list.remove(5);//1110
        System.out.println("list="+list);
//        list=[kerwin, 1110, hsp, true, hello, 3.14]

        //修改第7个元素
        System.out.println(list.size());//6
        list.add("我是第七个元素");
        System.out.println(list);
//        [kerwin, 1110, hsp, true, hello, 3.14, 我是第七个元素]
        list.set(6,"我是被改动之后的七号元素");
        System.out.println("此刻的list="+list);
//        此刻的list=[kerwin, 1110, hsp, true, hello, 3.14, 我是被改动之后的七号元素]

        //使用迭代器遍历集合
        System.out.println("使用迭代器遍历,可得:=======================");
        //创建迭代器,注意不是直接new哈
        Iterator iterator = list.iterator();
        //联想到迭代器的结构,判断是否还有下一个元素,若有,则下移,并return取出
        //顺便一提,可以用快捷键一键生成itit
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            System.out.println(obj);
        }
        //输出如下
        /**
         * kerwin
         * 1110
         * hsp
         * true
         * hello
         * 3.14
         * 我是被改动之后的七号元素
         */


    }
}

List的三种遍历方式

【ArrayList、LinkedList、Vector】

说明:使用LinkedList完成 ,其使用方式和ArrayList一样

public class Journey {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        //下面三种List接口的实现子类都可以完美适配底下三种遍历方式
//        LinkedList list = new LinkedList();
//        List list = new Vector();
        List list = new ArrayList();
        for (int i = 0; i < 5; i++) {
            list.add(i);
        }
        list.add("bingo!!");
        System.out.println(list);

        //1.使用迭代器遍历
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            System.out.println("obj=" + obj);
        }
        System.out.println("+++++++++++++++++++++++++++++++++++++++");
        //2.使用增强for循环
        for (Object o : list) {
            System.out.println("增强for得到元素-->" + o);
        }
        System.out.println("========================================");
        //3.使用普通for循环
        for (int i = 0; i < list.size(); i++) {
            System.out.println("normalFor===》" + list.get(i));
        }
    }
}
练习

在这里插入图片描述

public class Journey {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        //使用ArrayList实现
//        List list = new ArrayList();
        //使用Vector实现
//        List list = new Vector();
        //使用LinkedList实现
        List list = new LinkedList();
        list.add(new Book("红楼梦","曹雪芹",100));
        list.add(new Book("西游记","吴承恩",10));
        list.add(new Book("水浒传","施耐庵",19));
        list.add(new Book("三国志","罗贯中",80));
        list.add(new Book("西游记","吴承恩",10));


        for (Object o :list) {
            System.out.println(o);
        }
        //遍历结果如下:
        /**
         * 名称:红楼梦		价格:100.0		作者:曹雪
         * 名称:西游记		价格:10.0		作者:吴承恩
         * 名称:水浒传		价格:19.0		作者:施耐庵
         * 名称:三国志		价格:80.0		作者:罗贯中
         * 名称:西游记		价格:10.0		作者:吴承恩
         */

        //按价格排序,从高到低
        //如何对集合进行排序呢?
        sort(list);
        System.out.println("======排序后的输出=======");
        for (Object o :list) {
            System.out.println(o);
        }
        //输出结果如下
        /**
         * ======排序后的输出=======
         * 名称:西游记		价格:10.0		作者:吴承恩
         * 名称:西游记		价格:10.0		作者:吴承恩
         * 名称:水浒传		价格:19.0		作者:施耐庵
         * 名称:三国志		价格:80.0		作者:罗贯中
         * 名称:红楼梦		价格:100.0		作者:曹雪芹
         */

    }
    //静态方法
    @SuppressWarnings({"all"})
    public static void sort(List list){
        //使用冒泡排序框架
        int size = list.size();
        for(int e=size-1;e>0;e--){
            for(int j=0;j<e;j++){
                //取出对象
//                Object o = list.get(j);
                //注意这里要向下转型,不然不是Book对象,咋获得其属性呢?
                //这里不需要使用中间变量哈,可以直接用set实现互换
                Book book1 = (Book)list.get(j);//原先的list.get(j)的返回类型是Object类型的
                Book book2 = (Book)list.get(j+1);
                if(book1.getPrice()>book2.getPrice()){
                    list.set(j,book2);
                    list.set(j+1,book1);
                }
            }
        }
    }
}

ArrayList的注意事项

  • 可以存放所有类型的元素,甚至是空元素null,ArrayList并且可以放入多个元素
public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(null);
        list.add("kerwin");
        list.add(null);
        for (Object o :list) {
            System.out.println(o);

        }
        /**
         * null
         * kerwin
         * null
         */
    }
  • ArrayList是由数组来实现数据存储的

  • ArrayList基本等同于Vector,除了ArrayList是线程不安全(但是其执行效率高啊hhhh)的外;

    在多线程情况下,不建议使用ArrayList

 	//ArrayList是线程不安全的,以下是其add方法源码,可见并没有同步关键字修饰
	public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }
	
	//而这是Vector底层的add方法源码,可以看到是有同步关键字synchronized修饰的
	public synchronized void addElement(E obj) {
        modCount++;
        ensureCapacityHelper(elementCount + 1);
        elementData[elementCount++] = obj;
    }

ArrayList底层操作机制源码分析

@SuppressWarnings({"all"})
public class Journey {
    public static void main(String[] args) {
        //使用无参构造器创建ArrayList对象
        ArrayList list = new ArrayList();
//        ArrayList list = new ArrayList(8);

        for (int i = 1; i <=10; i++) {
            list.add(i);//这里会自动装箱,进入Integer的valueOf方法
            //之后,再执行这个add方法,而add方法内部也不是上来就把元素丢进数组里,
            //而是先通过ensureCapacityInternal方法来确保加了一个元素后,不会越界
            //然后才放进elementData数组中
        }

        for (int i = 11; i <= 15; i++) {
            list.add(i);
        }
        list.add(100);
        list.add(200);
        list.add(null);
        for (Object o :list) {
            System.out.println(o);

        }

    }
}
  • ArrayList中维护了一个Object类型的数组elementData

    拓展:transient–瞬间的、短暂的,其表示被transient修饰的属性不会被序列化,会被忽略

	public ArrayList() {
        //创建了一个空的elementData数组={}
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
        //这里再进入,就会发现起初这里传给它的DEFAULTCAPACITY_EMPTY_ELEMENTDATA是一个{}
    }
  • 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍
//calculateCapacity()--->grow()--->ensureExplicitCapacity()-->ensureCapacityInternal()--->add()
/**
调用顺序总结:
calculateCapacity() 计算出所需的最小容量。
结果传递给 ensureExplicitCapacity(),判断是否需要扩容。
如果需要扩容,ensureExplicitCapacity() 调用 grow() 方法进行扩容。
扩容完成后,所有调用链返回到 add() 方法,最终新元素被成功添加。
*/
	public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;//最后完成第一次扩容后,elementData就有了10个空间,size起初等于0,
        					  //把要放的数据放进去,然后size++,变为1,表示此时的数组中有了一个数据
        return true;
    }

    private void ensureCapacityInternal(int minCapacity) {//注意这里是最少需要的容量,比如你第一次add,那么最少需要一个
        //容量,嗯哼?如果你加了10个元素了,那么再add一次,底层到这儿就会是11个,因为只有11个才能将你之前的10个和
        //现在准备新add的那一个元素全放进去;
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        //如果当前数组是默认的空数组,则直接返回max(默认初始化的容量10,当前所需要的容量),否则返回所需容量
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            //DEFAULT_CAPACITY这里是10,而minCapacity是1
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        //这里的minCapacity是当前需要的最小容量,你当前要加进去一个元素,自然这里的值就是1了
        return minCapacity;
    }

    private void ensureExplicitCapacity(int minCapacity) {
        //这里记录的是被修改的次数
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)//10-0>0,所以进入动态扩容机制
            grow(minCapacity);
    }

	 private void grow(int minCapacity) {
        // overflow-conscious code
         //获取当前数组的容量
        int oldCapacity = elementData.length;//0
         //新数组扩容为原来的1.5倍,这里我们是第一次扩容,所以走的是第一个if逻辑分支
        int newCapacity = oldCapacity + (oldCapacity >> 1);//0+0/2=0
         //检查新的容量是否满足最小需求minCapacity,
         //如果不满足,也就是扩容后小于所需容量,则直接将 newCapacity 
         //设置为 minCapacity。这样可以确保扩容后的数组至少能容纳当前所有的元素。
        if (newCapacity - minCapacity < 0)//0<10,所以newCapacity就被赋成10了;
            newCapacity = minCapacity;
         //检查是否超过最大允许的数组大小
         //如果新的容量超过了这个最大值,就调用 hugeCapacity(minCapacity),
         //可能会根据系统的限制或特定情况处理超大数组的分配。
        if (newCapacity - MAX_ARRAY_SIZE > 0)//此时不满足,所以跳过
            newCapacity = hugeCapacity(minCapacity);

         //复制数组到新容量,elementData起初是{},newCapacity是10,
         //随后elementData容量就成了10,里面是空数据
        elementData = Arrays.copyOf(elementData, newCapacity);
         //这里的扩容是保留原有数据的前提下,再给你多搞几个空间出来,
         //类似于给你搬家,换个大房子,原先的东西也一并带过来
    }


扩容机制的要点

初始容量:在首次添加元素时,ArrayList 会初始化其内部数组到默认容量(10)。

动态扩容:每当数组需要扩容时,ArrayList 会扩展到原来容量的 1.5 倍,以减少频繁扩容的开销。

最小容量保证:扩容后的新容量至少满足当前所需的最小容量 minCapacity

最大容量检查:确保扩容后的容量不超过 JVM 所能支持的最大数组大小。

数组复制:通过扩展数组并复制原有数据,ArrayList 保证了动态数组的灵活性和稳定性。

  • 如果使用的是指定大小的构造器,则初始elementData的容量大小为指定大小,如果需要再次扩容,则直接扩容elementData为1.5倍
@SuppressWarnings({"all"})
public class Journey {
    public static void main(String[] args) {
        //使用有参构造器创建ArrayList对象
        ArrayList list = new ArrayList(8);

        for (int i = 1; i <=10; i++) {
            list.add(i);//这里会自动装箱,进入Integer的valueOf方法
            //之后,再执行这个add方法,而add方法内部也不是上来就把元素丢进数组里,
            //而是先通过ensureCapacityInternal方法来确保加了一个元素后,不会越界
            //然后才放进elementData数组中
        }

        for (int i = 11; i <= 15; i++) {
            list.add(i);
        }
        list.add(100);
        list.add(200);
        list.add(null);
        for (Object o :list) {
            System.out.println(o);

        }

    }
}

//debug源码,进入ArrayList的内部,如下,此时指定的容量是8,所以走第一个分支,给elementData扩容成8
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

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

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

相关文章

基于Video-Retalking-Gradio的AI数字人

随着数字内容的普及,如何在视频中实现高精度的音频与唇形同步成为一个重要课题。传统方法通常需要大量的人工干预和调整,效果也往往不尽如人意。为了应对这一挑战,VideoReTalking 系统应运而生。由西安电子科技大学和腾讯AI实验室的研究人员联合开发,VideoReTalking 是一个…

【微信小程序】微信小程序如何使用 MobX 进行状态管理?

微信小程序官方在 2019 年针对小程序发布了 MobX 辅助绑定库&#xff0c;可以让我们在微信小程序中使用 Mobx 进行状态管理&#xff1a; mobx-miniprogram&#xff1a;相当于 MobX&#xff1b;mobx-miniprogram-bindings&#xff1a;针对小程序的 MobX 辅助绑定库&#xff0c;…

【全志H616】【开源】 ARM-Linux 智能分拣项目:阿里云、网络编程、图像识别

【全志H616】【开源】 ARM-Linux 智能分拣项目&#xff1a;阿里云、网络编程、图像识 文章目录 【全志H616】【开源】 ARM-Linux 智能分拣项目&#xff1a;阿里云、网络编程、图像识1、实现功能2、软件及所需环境3、逻辑流程图及简述3.1 完整逻辑流程图3.2 硬件接线3.3 功能简述…

【TomCat】安装部署

首先得进行Java的安装和部署java1.8对应tomcat9 TomCat下载Apache Tomcat - Apache Tomcat 10 Software Downloads

Vue(四) 组件、单文件组件、非单文件组件,重要的内置关系

文章目录 1. 组件2. 非单文件组件2.1 定义组件2.2 注册组件2.3 使用组件2.4 组件命名、标签等注意点2.5 组件嵌套2.6 VueComponent构造&#xff08;这部分看视频更易理解&#xff09;2.7 内置关系 3. 单文件组件 1. 组件 组件是实现局部功能代码和资源的集合 传统方式&#x…

unreal engine5.4.3动画重定向

UE5系列文章目录 文章目录 UE5系列文章目录前言 前言 ue5.4和ue3动画重定向之间存在差异&#xff0c;跟ue5.2差别更大一点&#xff0c;总之ue5.4越来越简化动画重定向&#xff0c;不想之前还需要制作RTG文件 这是ue5.3.2的制作动画重定向的界面 这是ue5.4.2的制作动画重定向…

华芯邦获AEC-Q车规级系列认证与AQG324认证的双重背书,碳化硅SiC-MOSFET半导体功率器件器件已在重点头部新能源汽车厂商模块验证中。

在获得AEC-Q车规级系列认证与AQG324认证的双重背书后&#xff0c;华芯邦的碳化硅SiC-MOSFET器件不仅巩固了其在新能源汽车领域的领先地位&#xff0c;更进一步加速了其在全球汽车供应链中的深度布局。这款车规级产品凭借其卓越的耐高温、低导通电阻及高开关频率等特性&#xff…

kubernetes里面那些事——————OpenEBS

OpenEBS存储 一&#xff0c;OpenEBS简介二&#xff0c;卷类型三&#xff0c;本地卷存储引擎类型四&#xff0c;复制卷存储引擎类型&#xff08;副本卷&#xff09;4.1 复制卷实现原理4.2 复制卷的优势 五&#xff0c;openebs存储引擎技术选型六&#xff0c;k8s中部署openebs服务…

项目延期,怎么有效调整计划,追赶进度

在项目管理过程中&#xff0c;项目延期是一个令人头疼但又无法完全避免的问题。无论是由内部因素还是外部因素导致&#xff0c;都会对项目的整体进度、成本和质量产生影响。 面对延期&#xff0c;关键在于如何迅速而有效地调整项目计划&#xff0c;以确保项目能够尽快回到正轨…

新版IDEA配置前进和后退、打开资源管理器等快捷按钮

新版IDEA&#xff0c;好像是IDEA2024版本开始就默认隐藏了工具条&#xff0c;这时一些很常用的快捷按钮&#xff0c;如前进、后退、打开资源管理器就无法使用。这里图文介绍&#xff0c;如何把这些配置出来。 具体操作如下&#xff1a; 1、选择 File / Settings(windows版)&am…

关于contextmenu-ui组件库

关于这个组件库把&#xff0c;主要用在个人博客制作中&#xff0c;而且由于作者很懒&#xff0c;已经一个多月没有更新了&#xff0c;甚至第二次更新都忘了修改md文件了。 这个组件库是使用vue3和TS来写的&#xff0c;关于引用&#xff0c;看这里 都有介绍的&#xff0c;直接…

计算机网络(八股文)

这里写目录标题 计算机网络一、网络分层模型1. TCP/IP四层架构和OSI七层架构⭐️⭐️⭐️⭐️⭐️2. 为什么网络要分层&#xff1f;⭐️⭐️⭐️3. 各层都有那些协议&#xff1f;⭐️⭐️⭐️⭐️ 二、HTTP【重要】1. http状态码&#xff1f;⭐️⭐️⭐️2. 从输入URL到页面展示…

边缘计算工业网关可以为工业企业生产提供哪些价值应用?天拓四方

在数字化、网络化、智能化高度融合的今天&#xff0c;工业领域正迎来一场深刻的变革。边缘计算工业网关&#xff0c;作为这场变革中的关键角色&#xff0c;以其强大的数据处理能力、高效的通信效率和灵活的部署方式&#xff0c;为智能制造注入了新的活力。本文将结合一个实际应…

【安卓13】解决HDMI OUT和耳机等设备接入时会解除静音问题

安卓原生定义了部分外部设备接入时是否静音&#xff0c;比如耳机、有线扬声器、HDMIOUT设备等&#xff0c;这些设备接入时&#xff0c;安卓会设置AudioSystem.STREAM_MUSIC为非静音状态 从代码里可以看出&#xff0c;当一个newDevice 接入时&#xff0c;会携带一个deviceID&am…

Java基于微信小程序的超市购物管理系统

1 简介 Java基于微信小程序的超市购物管理系统&#xff0c;此超市购物系统利用当下成熟完善的springboot框架&#xff0c;使用跨平台的可开发大型商业网站的Java语言&#xff0c;以及最受欢迎的RDBMS应用软件之一的Mysql数据库进行程序开发。实现了收货地址管理、购物车管理、…

Win11 / Win10 系统极化工具,降低游戏延迟效果明显

Win11 / Win10 系统优化工具,降低游戏延迟效果明显 Windows 系统优化就是精简系统一些功能组件、对一些系统功能进行设置等&#xff0c;这样可以减少不必要的硬件资源占用。 全面的系统优化功能外&#xff0c;据不少网友表示通过优化后 CS GO 游戏降低输入延迟效果明显。 免费…

领夹麦克风哪个牌子音质好?西圣、博雅、枫笛领夹麦克风对比

当今的直播、短视频已经深深的融入到了我们的生活当中&#xff0c;很多小伙伴会通过拍摄短视频、Vlog来分享自己生活精彩的瞬间。不过录制视频时&#xff0c;如果单纯靠手机拾音会发现&#xff0c;音频效果是极差的&#xff0c;特别距离手机越远效果会越明显&#xff0c;会出现…

【从问题中去学习k8s】k8s中的常见面试题(夯实理论基础)(二十二)

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》&#xff1a;python零基础入门学习 《python运维脚本》&#xff1a; python运维脚本实践 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8…

一文直接搞懂SpringMVC完整版教程

三、SpringMVC 1、SpringMVC简介 1.1、什么是MVC MVC是一种软件架构的思想&#xff0c;将软件按照模型、视图、控制器来划分 M&#xff1a;Model&#xff0c;模型层&#xff0c;指工程中的JavaBean&#xff0c;作用是处理数据 JavaBean分为两类&#xff1a; 一类称为实体…