java基础 -02java集合之 List,AbstractList,ArrayList介绍

补充上篇

AbstractCollection < E >

在正式List之前,我们先了解我们补充上篇Collection接口的拓展实现,也就是说当我我们需要实现一个不可修改的Collection的时候,我们只需要拓展某个类,也就是AbstractCollection这个类,他是Collection接口的骨干实现,并以最大限度的实现了减少此接口所需要的工作;
在这里插入图片描述
在这里插入图片描述
如上两图进行比较即可。

我们可以拓展Collection,然后提供iterator和size方法的实现即可,其中我们的iterator方法返回迭代器必须实现一个hasNext和next。

注意:

  • AbstractCollection<E>是一个抽象类,不能直接实例化。如果需要使用它的方法,需要创建一个继承自它的子类,并实现Collection<E>接口中的所有方法。

  • AbstractCollection<E>提供了size()和isEmpty()方法的默认实现,但是它们都是基于iterator()方法实现的。如果子类有更高效的实现方式,可以重写这些方法。

  • AbstractCollection<E>提供了contains(Object o)和remove(Object o)方法的默认实现,但是它们都是基于iterator()方法实现的。如果子类有更高效的实现方式,可以重写这些方法。

  • AbstractCollection<E>没有提供add(E e)addAll(Collection<? extends E> c)方法的默认实现,因为这些方法的实现方式可能因子类而异。如果子类需要实现这些方法,需要自行实现。

  • AbstractCollection<E>提供了clear()和toArray()方法的默认实现,但是它们都是基于iterator()方法实现的。如果子类有更高效的实现方式,可以重写这些方法。

  • AbstractCollection<E>提供了toString()方法的默认实现,但是它只是简单地将集合中的元素转换为字符串并拼接在一起。如果子类需要更复杂的字符串表示方式,可以重写这个方法。

补充:
要实现一个可以修改的Collection,我们必须重新add方法,不然就会抛出异常,UnsupportedOperationException,iterator 方法返回的迭代器还必须另外实现其 remove 方法。

List

在这里插入图片描述
List是java中有序的、允许重复的、值可以为NULL的。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。

List 接口在 iterator、add、remove、equals 和 hashCode 方法的协定上加了一些其他约定,超过了 Collection 接口中指定的约定。

List接口中的元素按照插入顺序排列,并且允许包含重复元素。

  • void add(int index, E element): 在指定位置插入指定元素。
  • boolean remove(Object element): 移除指定元素的第一个匹配项。
  • E remove(int index): 移除指定位置的元素。
  • E get(int index): 返回指定位置的元素。
  • E set(int index, E element): 替换指定位置的元素。
  • int indexOf(Object element): 返回指定元素第一次出现的位置。
  • int lastIndexOf(Object element): 返回指定元素最后一次出现的位置。
  • List<E> subList(int fromIndex, int toIndex): 返回指定范围的子列表。

List接口有多个实现类,常见的有ArrayList、LinkedList和Vector等。

  • ArrayList是基于动态数组实现的,它支持快速随机访问和高效的插入、删除操作。适用于频繁访问元素的场景。

  • LinkedList是基于双向链表实现的,它支持高效的插入、删除操作,但访问元素的效率较低。适用于频繁插入、删除元素的场景。

  • Vector是线程安全的,它与ArrayList类似,但是性能较低。在多线程环境下,可以使用Vector来保证线程安全。

public class ListExample {public static void main(String[] args) {List<String> list = new ArrayList<>();// 添加元素list.add("apple");list.add("banana");list.add("orange");// 获取元素String firstElement = list.get(0);System.out.println("First element: " + firstElement);// 修改元素list.set(1, "grape");// 删除元素list.remove("orange");// 遍历元素for (String element : list) {System.out.println(element);}// 判断元素是否存在boolean contains = list.contains("apple");System.out.println("Does list contain 'apple'? " + contains);// 获取列表的大小int size = list.size();System.out.println("List size: " + size);// 获取子列表List<String> subList = list.subList(0, 2);System.out.println("Sublist: " + subList);}
}

AbstractList

AbstractList是List接口的一个抽象实现类,它提供了List接口中的一些通用实现,使得实现List接口的子类可以更加方便地实现自己的方法。如下图所示:
在这里插入图片描述
注意事项:

  • AbstractList是一个抽象类,不能直接实例化。如果需要使用它的方法,需要创建一个继承自它的子类,并实现List接口中的所有方法。
    在这里插入图片描述
public class MyList<E> extends AbstractList<E> {private Object[] elements;private int size;public MyList(int initialCapacity) {elements = new Object[initialCapacity];size = 0;}@Overridepublic E get(int index) {if (index < 0 || index >= size) {throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);}return (E) elements[index];}@Overridepublic int size() {return size;}@Overridepublic boolean add(E element) {if (size == elements.length) {resize();}elements[size++] = element;return true;}@Overridepublic E remove(int index) {if (index < 0 || index >= size) {throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size);}E removedElement = (E) elements[index];for (int i = index; i < size - 1; i++) {elements[i] = elements[i + 1];}elements[--size] = null;return removedElement;}private void resize() {int newCapacity = elements.length * 2;Object[] newElements = new Object[newCapacity];System.arraycopy(elements, 0, newElements, 0, size);elements = newElements;}
}

在上述代码中 我们创建了一个名为MyList的类,它继承自AbstractList类,并实现了get(int index)、size()、add(E element)和remove(int index)方法。

get(int index)方法用于获取指定索引位置的元素。我们在方法中进行了边界检查,并将元素强制转换为泛型类型。
size()方法返回列表的大小。

add(E element)方法用于向列表末尾添加元素。如果列表已满,我们会调用resize()方法来扩容。

remove(int index)方法用于移除指定索引位置的元素。我们在方法中进行了边界检查,并将被移除的元素返回。移除元素后,我们需要将后面的元素向前移动,并将最后一个位置置为null。

ArrayList

这个在我们面试过程中经常会碰到。
在这里插入图片描述

下面我们围绕ArrayList进行相关介绍:
在这里插入图片描述

  1. ArrayList作为Java中最常用的动态数组实现,他实现了List接口,由上图可以见到,其继承的AbstractList类实现的List接口,他可以动态地增加或者删除元素。注意一下他底层是数组,并且是可以扩充的数组。既然他是数组实现的,我们都知道如果是数组元素,那么随机访问速度会很快,但有优点就有缺点,查询速度快了,那么删除或者插入就慢,我们在ArrayList中插入或者删除元素的时候需要移动后面的元素,从而导致他的速度慢。
  2. ArrayList是非线程安全的,如果需要在多线程环境下使用,需要进行同步处理
  3. ArrayList的默认初始容量为10,如果需要存储更多的元素,可以在创建ArrayList对象时指定初始容量

ArrayList 的扩容机制

既然说到了ArrayList的扩容,那么我们来了解一下ArrayList的扩容机制吧:

  1. 初始容量:当创建一个新的ArrayList对象时,它会分配一个初始容量。默认情况下,初始容量为10,但也可以通过构造函数指定其他初始容量

  2. 容量增长:当ArrayList的元素数量超过当前容量时,ArrayList会自动增加其容量。容量增长的策略是通过创建一个更大的数组,并将原始数组中的元素复制到新数组中来实现的

  3. 增长因子:ArrayList的容量增长是按照增长因子来计算的。增长因子是一个大于1的值,用于确定新容量相对于当前容量的增长量。默认情况下,增长因子为1.5,这意味着新容量将是当前容量的1.5倍,比如说10,经过一次扩容为 10 * 1.5 = 15。

  4. 扩容操作:当需要扩容时,ArrayList会创建一个新的数组,并将原始数组中的元素复制到新数组中。这个操作涉及到数组的复制,因此在扩容时会有一定的性能开销

  5. 扩容策略:ArrayList的扩容策略是相对保守的,它会尽量避免频繁的扩容操作。当需要扩容时,ArrayList会根据当前容量和增长因子计算出一个新的容量,然后将新容量设置为ArrayList的容量。这样做的目的是为了减少扩容操作的频率,提高性能。

在这里插入图片描述

代码示例

import java.util.ArrayList;public class ArrayListExample {public static void main(String[] args) {// 创建一个ArrayList对象ArrayList<String> list = new ArrayList<>();// 向ArrayList中添加一个元素list.add("apple");list.add("banana");// 在指定位置插入一个元素list.add(1, "orange");// 删除指定位置的元素list.remove(1);// 删除指定元素list.remove("apple");// 获取指定位置的元素String fruit = list.get(0);// 替换指定位置的元素list.set(0, "orange");// 获取ArrayList中元素的数量int size = list.size();// 清空ArrayList中的所有元素list.clear();// 判断ArrayList中是否包含指定元素boolean containsApple = list.contains("apple");// 获取指定元素在ArrayList中的位置int index = list.indexOf("banana");}
}

在这里插入图片描述

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

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

相关文章

ChatGPT4+Python近红外光谱数据分析及机器学习与深度学习建模

2022年11月30日&#xff0c;可能将成为一个改变人类历史的日子——美国人工智能开发机构OpenAI推出了聊天机器人ChatGPT3.5&#xff0c;将人工智能的发展推向了一个新的高度。2023年4月&#xff0c;更强版本的ChatGPT4.0上线&#xff0c;文本、语音、图像等多模态交互方式使其在…

安全漏洞周报(2024.01.01-2023.01.08)

漏洞速览 ■ 用友CRM系统存在逻辑漏洞 漏洞详情 1. 用友CRM系统存在逻辑漏洞 漏洞介绍&#xff1a; 某友CRM系统是一款综合性的客户关系管理软件&#xff0c;旨在帮助企业建立和维护与客户之间的良好关系。它提供了全面的功能&#xff0c;包括销售管理、市场营销、客户服…

1.10 Unity中的数据存储 XML

一、XML 1.介绍 XML是一个文档后缀名是*.xmlXML是一个特殊格式的文档XML是可扩展的标记性语言XML是Extentsible Markup Language的缩 写XML是由万维网联盟(W3C)创建的标记语言&#xff0c;用于定义编码人类和机器可以读取的文档的语法。它通过使用定义文档结构的标签以及如何…

代码随想录算法训练营第二十一天| 回溯 216. 组合总和 III 17. 电话号码的字母组合

216. 组合总和 III 可以参考77.组合中关于选取数组的相关操作。 递归函数的返回值以及参数&#xff1a;一般为void类型 递归函数终止条件&#xff1a;path这个数组的大小如果达到k&#xff0c;说明我们找到了一个子集大小为k的组合了&#xff0c;然后当n为0的时候&#xff0…

Maven报错:Malformed \uxxxx encoding 解决办法

maven构建出现这个Malformed \uxxxx encoding问题&#xff0c;应该是maven仓库里面有脏东西进入了&#xff01; 解决&#xff1a; 将仓库中的resolver-status.properties文件全部干掉。 我使用的everything工具全局搜索resolver-status.properties文件&#xff0c;然后Ctrla,再…

Nodejs 第三十一章(响应头和请求头)

响应头 HTTP响应头&#xff08;HTTP response headers&#xff09;是在HTTP响应中发送的元数据信息&#xff0c;用于描述响应的特性、内容和行为。它们以键值对的形式出现&#xff0c;每个键值对由一个标头字段&#xff08;header field&#xff09;和一个相应的值组成。 例如…

第三十九级台阶

解题思路&#xff1a; 本题运用递归的思想&#xff0c;每走一步可以上一个或者两个台阶&#xff0c;一开始是左脚最后是右脚&#xff0c;所以走的总步数应该为偶数&#xff0c;最后跨过的台阶数应该等于39。 解题代码&#xff1a; public class disnashijiujitaijie {static i…

03. BI - 详解机器学习神器 XGBoost

本文专辑 : 茶桁的AI秘籍 - BI篇 原文链接: https://mp.weixin.qq.com/s/kLEg_VcxAACy8dH35kK3zg 文章目录 集成学习XGBoost Hi&#xff0c;你好。我是茶桁。 学习总是一个循序渐进的过程&#xff0c;之前两节课的内容中&#xff0c;咱们去了解了LR和SVM在实际项目中是如何使…

100V耐压 LED恒流驱动芯片 SL2516D兼容替换LN2516车灯照明芯片

SL2516D LED恒流驱动芯片是一款专为LED照明设计的高效、高精度恒流驱动芯片。与LN2516车灯照明芯片兼容&#xff0c;可直接替换LN2516芯片&#xff0c;为LED车灯照明提供稳定、可靠的电源解决方案。 一、SL2516D LED恒流驱动芯片的特点 1. 高效率&#xff1a;SL2516D采用先进的…

HarmonyOS4.0系统性深入开发17进程模型概述

进程模型概述 HarmonyOS的进程模型&#xff1a; 应用中&#xff08;同一包名&#xff09;的所有UIAbility运行在同一个独立进程中。WebView拥有独立的渲染进程。 基于HarmonyOS的进程模型&#xff0c;系统提供了公共事件机制用于一对多的通信场景&#xff0c;公共事件发布者…

深度解析-Java语言的未来

深度解析-Java语言的未来&#xff0c;文末有我耗时一个月&#xff0c;问遍了身边的大佬&#xff0c;零基础自学Java的路线&#xff0c;适用程序员入门&进阶&#xff0c;Java学习路线&#xff0c;2024新版最新版。 文章目录 Q1 - 能否自我介绍下&#xff1f; Q2 - Java语…

设计模式——抽象工厂模式(Abstract Factory Pattern)

概述 抽象工厂模式的基本思想是将一些相关的产品组成一个“产品族”&#xff0c;由同一个工厂统一生产。在工厂方法模式中具体工厂负责生产具体的产品&#xff0c;每一个具体工厂对应一种具体产品&#xff0c;工厂方法具有唯一性&#xff0c;一般情况下&#xff0c;一个具体工厂…

数据结构与算法之美学习笔记:46 | 概率统计:如何利用朴素贝叶斯算法过滤垃圾短信?

目录 前言算法解析总结引申 前言 本节课程思维导图&#xff1a; 上一节我们讲到&#xff0c;如何用位图、布隆过滤器&#xff0c;来过滤重复的数据。今天&#xff0c;我们再讲一个跟过滤相关的问题&#xff0c;如何过滤垃圾短信&#xff1f; 垃圾短信和骚扰电话&#xff0c;我…

docker安装nodejs,并更改为淘宝源

拉取官方 Node.js 镜像 docker pull node:latest创建 Dockerfile&#xff0c;并更改 NPM 下载源为淘宝源&#xff0c;设置为全局持久化 # 使用最新版本的Node.js作为基础镜像 FROM node:latest# 设置工作目录为/app WORKDIR /app # 更改 NPM 下载源为淘宝源&#xff0c;并设置…

c++学习笔记-STL案例-机房预约系统1-需求分析

1 机房预约系统需求 1.1 简单介绍 学校有几个规格不同的机房&#xff0c;由于使用经常出现“撞车”现象&#xff0c;现在开发一套预约系统&#xff0c;解决这一问题。 1.2 身份介绍 分别有三种身份使用该系统 学生代表&#xff1a;申请使用机房教师&#xff1a;审核学生的…

从单细胞数据分析的最佳实践看R与Python两个阵营的博弈

R与Python&#xff0c;在生物信息学领域的博弈异常激烈。许多生信分析&#xff0c;两个阵营都发展出了自己的方法&#xff0c;比如单细胞数据分析&#xff0c;R有Seurat&#xff0c;Python就有Scanpy。这些层出不穷的方法不断地吸引着吃瓜群众的眼球&#xff0c;同时也让人患上…

Qt 6之六:Qt Designer介绍

Qt 6之六&#xff1a;Qt Designer介绍 Qt Designer是一个可视化的用户界面设计工具&#xff0c;用于创建Qt应用程序的用户界面&#xff0c;允许开发人员通过拖放和布局来设计和创建GUI界面。 Qt 6之一&#xff1a;简介、安装与简单使用 https://blog.csdn.net/cnds123/articl…

Linux 文件(夹)权限查看

命令 : ls -al ls -al 是一个用于列出指定目录下所有文件和子目录的命令,包括隐藏文件和详细信息。其中,-a 选项表示显示所有文件,包括以 . 开头的隐藏文件,-l 选项表示以列表的形式显示文件的详细信息。 本例中:drwxrwxr-x 为权限细节。 权限细节(Permission detail…

DePIN:重塑物理资源网络的未来

点击查看TechubNews更多相关推荐 一、DePIN&#xff1a;物理资源的新整合方式 Depin赛道的项目如雨后春笋般涌现&#xff0c;为市场注入了新的活力。作为先行者&#xff0c;Coinmanlabs已经深入布局Depin赛道&#xff0c;其中最引人注目的项目当属Grass。 什么是DePIN DePIN…

uniapp在web端怎么使用svg图标呢

在图标库中添加好项目用到的图标&#xff0c;点击symbol点击生成在线链接 点击生成的在线链接&#xff0c;此时会跳转到一个新窗口&#xff0c;是一个js文件 复制这个js文件的内容 然后在uniapp中新建svg.js文件&#xff0c;把从上面复制的代码粘贴到这个svg.js中 在main.js中引…