List 接口常用实现类底层分析

news2024/11/27 6:35:27

一、集合

1.1 简介

        集合主要分为两组(单列集合、双列集合),Collection 接口有两个重要的子接口 List Set,它们的实现子类都是单列集合。Map 接口的实现子类是双列集合,存放的是 K-V

1.2 关系图

二、Collection 接口和常用方法

public interface Collection<E> extends Iterator<E>

2.1 特点

        1、Collection 实现子类可以存放多个元素,每个元素可以是 Object

        2、有些 Collection 的实现类可以存放重复元素,有些不可以。

        3、有些 Collection 的实现类是有序的(List),有些不是有序的(Set

        4、Collection 接口没有直接的实现子类,是通过它的子接口 Set List 来实现的

2.2 常用方法

        下面使用实现类 ArrayList 来演示,如下

public class CollectionTest {
    public static void main(String[] args) {
        Collection list = new ArrayList();
        // add: 添加单个元素
        list.add("java");
        list.add(10);
        list.add(true);
        System.out.println("list="+list);

        // remove: 删除指定元素
        list.remove(true);
        System.out.println("list="+list);
        
        // contains: 查找元素是否存在
        System.out.println(list.contains("java"));
        
        // size: 获取元素个数
        System.out.println("现在集合的大小为:"+list.size());
        
        // isEmpty: 判断是否为空
        System.out.println("判断集合是不是空的"+list.isEmpty());
        
        // clear: 清空集合
        list.clear();
        System.out.println("我要清空集合了,现在集合的大小为:"+list.size());

        // addAll: 添加多个元素
        ArrayList list2 = new ArrayList();
        list2.add("苹果");
        list2.add("香蕉");
        list.addAll(list2);
        System.out.println("添加完多个元素后集合的大小为:"+list.size());
        
        // containsAll: 查找多个元素是否都存在
        System.out.println("查找多个元素是否都存在:"+list.containsAll(list2));
        
        // removeAll: 删除多个元素
        list.removeAll(list2);
        System.out.println("删除多个元素后集合的大小为:"+list.size());
    }
}

2.3 接口遍历

2.3.1 Iterator 方式

        Iterator 对象称为迭代器,主要用于遍历 Collection 集合中的元素。所有实现了 Collection 接口的集合类都有一个 iterator() 方法,用于返回一个实现了 Iterator 接口的对象,即可以返回一个迭代器。

        需要注意的是,在调用 iterator.next() 方法之前必须要调用 iterator.hasNext() 方法进行检测,若不调用最终会报异常。

        如果希望再次遍历,则需要重置我们的迭代器,即重新调用下 coll.iterator() 方法即可。

// 得到一个集合的迭代器
Iterator iterator = coll.iterator();
// 判断是否还有下一个元素
while(iterator.hasNext()){
	// next() 方法有两个作用:下移并且将下移以后集合位置上的元素返回
	System.out.println(iterator.next());
}

2.3.2 for 循环方式

        增强 for 循环,可以代替 iterator 迭代器。它就是简化版的 iterator,本质是一样的,只能用于遍历集合或数组。

for(元素类型 元素名:集合或数组名){

    // 访问元素
}

三、List 接口和常用方法

3.1 特点

        1、List 集合类中元素有序(即添加顺序和取出顺序是一致的)、且可重复。

        2、List 集合中每个元素都有其对应的顺序索引,即支持索引。

        3、List 容器中的元素都对应一个整数型的序号记录其在容器中的位置,可以根据序号存取容器中的元素。

3.2 常用实现类

        ArrayListLinkedListVector

3.3 常用方法

public class ListMethod {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("苹果");
        list.add("香蕉");

        // add(int index,Object ele): 在 index 位置插入 ele 元素
        list.add(1,"西瓜");
        System.out.println("list="+list);

        // addAll(int index,Collection els):从 index 位置开始将 els 中的所有元素添加进来
        List list2 = new ArrayList();
        list2.add("足球");
        list2.add("篮球");
        list.addAll(0,list2);
        System.out.println("list="+list);

        // Object get(int index):获取指定 index 位置的元素
        System.out.println(list.get(0));

        // int indexOf(Object obj):返回 obj 在集合中首次出现的位置
        System.out.println(list.indexOf("足球"));
        
        // int lastIndexOf(Object obj):返回 obj 在集合中末次出现的位置
        System.out.println(list.lastIndexOf("篮球"));
        
        // Object remove(int index):移除指定 index 位置的元素,并返回此元素
        System.out.println(list.remove(0));
        
        // Object set(int index,Object obj):设定指定 index 位置的元素为 obj,相当于是替换
        list.set(2,"美女");
        System.out.println("list="+list);
        
        // List subList(int fromIndex,int toIndex):返回从 fromIndex 到 toIndex 位置的子集合,左闭右开
        List list3 = list.subList(2,3);
        System.out.println("list3="+list3);
    }
}

3.4 排序方法

// 按照 Book 类的 price 属性从小到大排序
public static void sort(List list){
	int size = list.size();
	for(int i=0;i<size-1;i++){
		for(int j=0;j<list.size()-1-i;j++){
			Book b1 = (Book)list.get(j);
			Book b2 = (Book)list.get(j+1);
			if(b1.getPrice()> b2.getPrice()){
				list.set(j,b2);
				list.set(j+1,b1);
			}
		}
	}
}

四、ArrayList 

4.1 特点

        ArrayList 可以添加 null,并且可以存储多个。底层是由数组来实现数据存储的,ArrayList 基本等同于 Vector,但是 ArrayList 是线程不安全的。

        ArrayList 中维护了一个 Object 类型的数组 elementData,如下:

// transient 表示该属性不会被序列化
transient Object [] elementData

4.2 无参扩容分析

        当创建 ArrayList 对象时,如果使用的是无参的构造器,则初始化 elementData 容量为 0,第一次添加元素的时候,elementData 会扩容为 10,如需要再次扩容,则扩容 elementData 1.5 倍。

public class ArrayListTest {
    public static void main(String[] args) {
        // 使用无参构造器创建 ArrayList 对象
        // 创建一个容量为 0 的 elementData 数组
        ArrayList list = new ArrayList();
        for(int i=1;i<=10;i++){
            // add() 方法:先判断是否需要扩容,然后再执行赋值
            // 如果进行扩容,则第一次扩容为10,第二次即以后按照 1.5 倍扩容
            list.add(i);
        }
        for(int i=11;i<=15;i++) {
            // 此时要进行第二次扩容为: 10+10/2 = 15
            list.add(i);
        }
        // 此时要进行第三次扩容为: 15+15/2=22
        list.add(100);
        list.add(200);
        list.add(null);
    }
}

4.3 有参扩容分析

        如果使用的是指定大小的构造器,则初始 elementData 容量为指定大小,如果需要扩容,则直接扩容 elementData 1.5 倍。

public class ArrayListTest2 {
    public static void main(String[] args) {
        // 使用有参构造器创建 ArrayList 对象
        // 创建一个容量为 8 的 elementData 数组
        ArrayList list = new ArrayList(8);
        for(int i=1;i<=10;i++){
            // add() 方法:先判断是否需要扩容,然后再执行赋值
            // 当 i=9 的时候需要进行扩容,此时按照 1.5 倍扩容:8+8/2 = 12
            list.add(i);
        }
        for(int i=11;i<=15;i++) {
            // 当 i=13 的时候,此时要进行第二次扩容为: 12+12/2 = 18
            list.add(i);
        }
        list.add(100);
        list.add(200);
        list.add(null);
    }
}

五、Vector

5.1 特点

        Vector 底层也是一个对象数组,它是线程安全,Vector 类的操作方法带有 synchronized 关键字修饰。当涉及到线程安全时,可以使用 Vector

5.2 无参扩容分析

        当创建 Vector 对象时,如果使用的是无参的构造器,则初始化 elementData 容量为 10,满了之后,扩容为 elementData  2 倍。

public class VectorTest {
    public static void main(String[] args) {
        // 使用无参构造器创建 Vector 对象
        // new Vector() 时会创建一个容量为 10 的 elementData 数组
        Vector list = new Vector();
        for(int i=1;i<=10;i++){
            // add() 方法:先判断是否需要扩容,然后再执行赋值
            list.add(i);
        }
        // 此时要进行第二次扩容为: 10+10=20
        list.add(100);
    }
}

5.3 有参扩容分析

        如果使用的是指定大小的构造器,则初始 elementData 容量为指定大小,满了之后,扩容为 elementData  2 倍。

public class VectorTest {
    public static void main(String[] args) {
        // 使用有参构造器创建 Vector 对象
        // new Vector() 时会创建一个容量为 7 的 elementData 数组
        Vector list = new Vector(7);
        for(int i=1;i<=10;i++){
            // add() 方法:先判断是否需要扩容,然后再执行赋值
            // 当 i=8 的时候需要进行第一次扩容,容量为:7+7= 14
            list.add(i);
        }
        list.add(100);
    }
}

六、LinkedList

6.1 特点

        LinkedList 底层实现了双向链表和双端队列的特点,可以添加任意元素,包括 null,线程不安全,没有实现同步。

6.2 底层结构

        1、LinkedList 底层维护了一个双向链表。

        2、LinkedList 中维护了两个属性 first last 分别指向首节点和尾节点。

        3、每个节点(Node 对象),里面又维护了 prevnextitem 三个属性,其中通过 prev 指向前一个,通过 next 指向后一个节点。最终实现双向链表。

        4、所以 LinkedList 的元素的添加和删除不是通过数组完成的,相对来说效率较高。

6.3 LinkedList 和 ArrayList 比较

底层结构增删的效率改查的效率
ArrayList可变数组较低,数组扩容较高
LinkedList双向链表较高,通过链表追加较低

如何选择 ArrayList LinkedList

        1、如果我们增删的操作多,选择 LinkedList

        2、如果我们改查的操作多,选择 ArrayList

        3、一般来说,在程序中,80%90% 都是查询,因此大部分情况下会选择 ArrayList

        4、在一个项目中,根据业务灵活选择,有可能是一个模块使用的是 ArrayList,另外一个模块是 LinkedList。也就是说,要根据业务来进行选择

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

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

相关文章

听说你的爬虫被封了?

目录 前言 一、为什么会被封IP&#xff1f; 二、代理IP是什么&#xff1f; 三、代理IP的分类 1. 公共代理IP 2. 私人代理IP 四、使用代理IP的方法 1. 使用第三方库 2. 手动设置代理IP 五、常见问题及解决方法 1. 代理IP不稳定 2. 代理IP被封 六、代码实例 总结 前…

城市内涝怎么预警?万宾科技内涝积水监测仪

在城市运行过程中&#xff0c;城市内涝问题频繁出现&#xff0c;影响城市管理水平的提升&#xff0c;也会进一步减缓城市基础设施建设。尤其近几年来&#xff0c;城市内涝灾害频繁出现&#xff0c;在沿海地区内涝所带来的安全隐患成为城市应急管理部门的心头大患。城市内涝的背…

文本批量处理,一键转换HTML文件编码,释放您的繁琐工作!

亲爱的用户&#xff0c;您是否曾经为需要手动转换HTML文件编码而耗费大量时间和精力而感到困扰&#xff1f;现在&#xff0c;我们为您提供了一款强大的文本批量处理工具&#xff01;让您一键将HTML文件编码进行转换&#xff0c;轻松释放您的繁琐工作&#xff01; 首先&#xf…

RabbitMQ部署指南:使用docker部署

RabbitMQ部署指南 1.单机部署&#xff08;为例&#xff09; 我们在Centos7虚拟机中使用Docker来安装。 1.1.下载镜像 方式一&#xff1a;在线拉取 docker pull rabbitmq:3-management方式二&#xff1a;从本地加载 在课前资料已经提供了镜像包&#xff1a; 上传到虚拟机中…

JS-数组定义

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>JS-对象</title> </head><body>&l…

Centos部署清华ChatGLM3-6B详细教程

来源: AINLPer公众号&#xff08;每日干货分享&#xff01;&#xff01;&#xff09; 编辑: ShuYini 校稿: ShuYini 时间: 2023-10-03 引言 上周末&#xff0c;智谱AI在2023中国计算机大会&#xff08;CNCC&#xff09;上推出了全自研的第三代基座大模型ChatGLM3&#xff0c;在…

芯片封装技术

一、概述 封装的作用 1.3 封装类型 1.3.1 打线封装&#xff08;Wire Bonding&#xff09; 打线封装是传统的封装方式&#xff0c;具体过程是将晶圆切割为晶粒&#xff08;Die&#xff09;后&#xff0c;使晶粒贴合到相应的基板架的小岛&#xff08;LeadframePad&#xff09…

leetcode:389. 找不同

一、题目 函数原型&#xff1a;char findTheDifference(char * s, char * t) 二、思路 作者原先的思路是先将两个字符串从小到大排序&#xff0c;然后两个字符串依次比较。若出现字符串t中的元素和字符串s不相等&#xff0c;则说明该元素就是被添加的字母。 但是&#xff0c;该…

在Spring中,教你一招优雅的获取国际化语言配置的方法

在Spring中,可以将国际化语言放到HTTP请求头部,以便后端程序能够获取并解析该语言。一种常见的方式是使用Accept-Language标头字段来设置语言。下面是一个示例代码,演示如何从HTTP请求头部获取该字段的值: 在 Spring 中,可以通过 HttpServletRequest 对象获取 HTTP 头部信…

【Spring】SpringWebMVC入门

Spring Web MVC入门 什么是SpringWebMVCMVC定义什么是SpringMVC 学习SpringMVC建立连接RequestMapping注解RequestMapping使用 请求传递单个参数传递多个参数传递对象后端参数重命名传递数组传递集合传递JSON获取URL中参数pathVariable上传文件RequestPart获取Cookie/Session获…

【市场分析】Temu数据采集销售额商品量占比分析数据分析接口Api

引言 temu电商平台是一个充满活力的电商平台&#xff0c;拥有多种商品类别和数万家店铺。在这个项目中我的任务是采集平台上的大量公开数据信息。通过数据采集&#xff0c;我旨在深入了解temu电商平台的产品分布、销售趋势和文本描述&#xff0c;以揭示有趣的见解。 数据采集…

Java web(四):JSP

文章目录 一、JSP1.1 概述1.2 JSP入门1.3 JSP脚本1.4 缺点 二、EI表达式三、JSTL3.1 标签3.2 JSTL使用3.3 代码演示 四、MVC模式和三层架构五、项目实战【完成增删改查】 一、JSP 1.1 概述 JSP&#xff08;全称&#xff1a;Java Server Pages&#xff09;&#xff1a;Java 服…

【UE 材质】简单的闪闪发光材质

效果 节点 参考视频&#xff1a; https://www.bilibili.com/video/BV1uK411y737/?vd_source36a3e35639c44bb339f59760641390a8

自动化测试--验证邮件内容

场景 业务上有许多发送邮件的场景&#xff0c;发送的邮件基本上都是自动发送的&#xff0c;而且邮件内容是很重要的&#xff0c;对于邮件发没发送&#xff0c;发送的时间点对不对每次回归测试工作量太大了&#xff0c;所以考虑把这部分内容加入到自动化测试中 工具 python g…

精选8款UML图工具,闭眼入!

在现代软件开发领域&#xff0c;UML&#xff08;统一建模语言&#xff09;图是不可或缺的工具之一&#xff0c;用于可视化和通信复杂系统的结构和设计。然而&#xff0c;在选择合适的UML图工具时&#xff0c;你需要考虑多个因素&#xff0c;如项目规模、团队协作需求、功能复杂…

【Unity实战】最全面的库存系统(四)

文章目录 先来看看最终效果前言问题新增数据库,自动添加物品唯一ID物品配置唯一的ID替换原来的instanceID丢弃物品每次只丢弃一个物品问题完结先来看看最终效果 前言 本期紧跟着上期,继续来完善我们的库存系统,实现存储物品唯一ID和加载功能,丢弃物品功能 问题 instance…

【方法】如何解压ZIP格式压缩文件?

ZIP是一种常见的压缩文件格式&#xff0c;可以将一个或多个文件和文件夹打包成单个文件&#xff0c;以减少存储空间和传输时间。那想要读取压缩包里的文件&#xff0c;要如何解压呢&#xff1f; 压缩和解压压缩包&#xff0c;都需要用到解压缩软件&#xff0c;下面来分享一下3…

一键翻译,批量重命名,让文件夹名更贴心!

在日常生活和工作中&#xff0c;我们经常需要处理大量的文件夹。有时候&#xff0c;我们需要根据特定的需求对这些文件夹进行重命名。但是&#xff0c;手动重命名每个文件夹不仅耗时且容易出错。现在&#xff0c;我们的文件改名工具为你提供了一键翻译、批量重命名的便捷服务&a…

C语言调试技巧(debug)及程序运行时出现的问题

目录 一、什么是调试 1.介绍调试 2.Debug与Release 3.Debug与Release的对比 二、怎么调试 1.介绍几个调试快捷键 2.调试的时候查看程序当前信息 三、常见编程错误 1.编译型错误&#xff08;最简单&#xff09; 2.链接型错误 3.运行时错误&#xff08;最难&#xff0…

stm32F407系列控制板用户手册

stm32F407系列控制板用户手册 文章目录 stm32F407系列控制板用户手册1.外观和接口标注2.功能3.参数4.应用场景 1.外观和接口标注 2.功能 智能配网远程控制多路舵机接口多路电机接口姿态实时采集ps 接口oled屏OTA固件一键升级语音控制-需借助app语音识别功能预留can接口预留多个…