快邀请你的冤种朋友一起来学习顺序表的底层逻辑:ArrayList集合

进来了就一起来学习如何去使用ArrayList这个集合吧! 

目录

一.ArrayList是什么

二.ArrayList的构造方法与扩容机制

 1.无参构造方法与扩容机制

2.带参数的构造方法

3.利用其他 Collection 构建 ArrayList

三.ArrayList常用方法介绍

1.插入数据方法

2.boolean contains(Object o) 方法

3.List subList(int fromIndex, int toIndex) 方法

4.remove方法

四.ArrayList的遍历方式

1.for循环遍历

2.使用迭代器遍历


一.ArrayList是什么

(1)为什么说ArrayList是一个动态顺序表

  • ArrayList底层是一段连续的空间,并且可以动态扩容,所以是一个动态的顺序表
  • 我们知道,我们实现顺序表的话,需要自己写它增删查改的方法,然后再调用;而ArrayList可以看作是一个已经实现好的顺序表,我们可以直接调用和使用

(2)从实现方面理解ArrayList

  • ArrayList是一个类,并且是一个泛型类(限制类型的作用),类中有许许多多的方法(可以类比String类)
  • 泛型类,所以使用的时候必须实例化
ArrayList<Integer> arrayList = new ArrayList<>();//实例化操作

(3)ArrayList实现的接口及拥有的功能 

  • ArryList实现了List接口,List是一个线性表,所以ArrayList就具备了顺序表的功能(本节重点)

  •  ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问
  • ArrayList实现了Cloneable接口,表明ArrayList是可以clone的
  • ArrayList实现了Serializable接口,表明ArrayList是支持序列化的

(4)简单使用ArrayList

  • 常规的实例化

格式:ArrayList<类型>  引用  =  new  ArrayList<>() 

ArrayList<Integer> arrayList = new ArrayList<>();//实例化操作
ArrayList<String> arrayList1 = new ArrayList<>();

  • 使用向上转型实例化

格式:List<类型>  引用  =  new  ArrayList<>()

List<Integer> list = new ArrayList<>();
List<String> list2 = new ArrayList<>();

  • 简单的添加数据和打印
 public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(3);
        list.add(1);
        list.add(4);
        list.add(5);
        list.add(2);
        list.add(0);
        System.out.println(list);
    }

二.ArrayList的构造方法与扩容机制

构造方法:

ArrayList() 无参构造
ArrayList(int initialCapacity) 指定顺序表初始容量
ArrayList(Collection<? extends E> c)利用其他 Collection 构建 ArrayList

ArrayList的成员变量:

private static final int DEFAULT_CAPACITY = 10;
private static final Object[] EMPTY_ELEMENTDATA = {};
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
transient Object[] elementData;
private int size;//记录当前顺序的大小

 1.无参构造方法与扩容机制

(1)认识和使用无参构造方法

  • 无参的构造方法是这样实例化对象的
ArrayList<Integer> arrayList = new ArrayList<>();
  • 原码的无参构造方法
 public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

(2)如何执行无参构造方法

从上面我们可以得到一个结论: 

 结论一:使用无参构造方法实例化对象时,是没有给顺序表分配内存空间的

(3)扩容机制

  • 先看一段代码
 public static void main(String[] args) {
        ArrayList<Integer> arrayList1 = new ArrayList<>();
        arrayList1.add(1);
        arrayList1.add(2);
        System.out.println(arrayList1);
    }

提出一个疑问?明明没有对该顺序表分配内存空间,为什么还可以对其赋值呢?下面走进add的原码一看究竟

  • 查看add的工作原理及增容机制

由上面我们可以得出结论:

结论二:第一次add(第一次增容)时,默认分配10的内存空间

  • 进行扩容操作的适时候

结论三:当扩容时,会按原内存的1.5倍进行扩容

2.带参数的构造方法

(1)认识和使用带参构造方法

  • 指定容量是是这样实例化对象的
 ArrayList<Integer> arrayList = new ArrayList<>(15);//指定开辟15个空间
  • 查看带参数的构造方法原码
  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);
        }
    }

 (2)如何执行构造方法

  • 当参数为负数时:运行时抛异常

3.利用其他 Collection 构建 ArrayList

这种构造方法是什么意思呢?也就是将其他的顺序表作为参数,下面一起来看看吧

(1)认识和使用该种构造方法

  •  使用该方法实例化对象
 public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(520);
        arrayList.add(1314);
        ArrayList<Integer> arrayList1 = new ArrayList<>(arrayList);//第三种构造方式
        System.out.println(arrayList1);
    }

  • 认识该构造方法的原码
public ArrayList(Collection<? extends E> c) {
        Object[] a = c.toArray();
        if ((size = a.length) != 0) {
            if (c.getClass() == ArrayList.class) {
                elementData = a;
            } else {
                elementData = Arrays.copyOf(a, size, Object[].class);
            }
        } else {
            // replace with empty array.
            elementData = EMPTY_ELEMENTDATA;
        }
    }

(2)认识原码的工作原理

  • 原码 

  • 参数需要满足的条件 

(3)使用该构造方法及错误原因

  • 通用的
  public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        List<Integer> list2 = new ArrayList<>(list);
        ArrayList<Integer> list3 = new ArrayList<>(list2);
        List<Integer> list4 = new ArrayList<>(list3);
        ArrayList<Number>  list5 = new ArrayList<>(list4);
    }

  • 错误案例

三.ArrayList常用方法介绍

常用的方法表格,如下所示:

方法功能
boolean add(E e) 尾插 e
void add(int index, E element) 将 e 插入到 index 位置
boolean addAll(Collection<? extends E> c) 尾插 c 中的元素
E remove(int index) 删除 index 位置元素并返回该元素
boolean remove(Object o) 删除遇到的第一个 o
E get(int index) 获取下标 index 位置元素
E set(int index, E element) 将下标 index 位置元素设置为 element
void clear() 清空顺序表
boolean contains(Object o) 判断 o 是否在线性表中
int indexOf(Object o) 返回第一个 o 所在下标
int lastIndexOf(Object o) 返回最后一个 o 的下标
List<E> subList(int fromIndex, int toIndex) 截取部分 list

1.插入数据方法

(1)boolean add(E e) 

默认尾插的方法

public static void main(String[] args) {
      ArrayList<Integer> arrayList = new ArrayList<>();
      arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        System.out.println(arrayList);
    }

(2)void add(int index, E element) 

指定位置插入数据

 public static void main(String[] args) {
      ArrayList<Integer> arrayList = new ArrayList<>();
      arrayList.add(0,9);
        arrayList.add(0,9);
        arrayList.add(0,7);
        System.out.println(arrayList);
    }

2.boolean contains(Object o) 方法

(1)方法目的:判断 o 是否在线性表中(o是一个字符串);也就是删除线性表中的存在字符串o(字符串o中的每一个字符都不能留)

(2)方法举例

  • str1 = "welcome to world",str2 = "come",要求,删除str1中存在的str2字符,并返回一个线性表
  • 代码:
private static ArrayList<Character> func(String str1,String str2) {
        //删除str1中的str2
        ArrayList<Character> arrayList = new ArrayList<>();
        for (int i = 0; i < str1.length(); i++) {
            char ch = str1.charAt(i);
            if(!str2.contains(ch+"")) {
                arrayList.add(ch);
            }
        }
        return arrayList;
    }
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        String str1 = "welcome to world";
        String str2 = "come";
        ArrayList<Character> arrayList1 = func(str1,str2);
        System.out.println(arrayList1);

    }

  • 本题细节点:字符+""(空字符串)可以变成字符串类型

3.List<E> subList(int fromIndex, int toIndex) 方法

(1)功能:截取指定范围内的数据

返回值:List接口定义的变量

(2)简单举例:

public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(10);
        arrayList.add(20);
        arrayList.add(30);
        arrayList.add(40);
        arrayList.add(50);
        System.out.println(arrayList);
        List<Integer> list = arrayList.subList(1,3);
        System.out.println(list);
    }

(3)subList的特点

  • 先看一段代码
public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(10);
        arrayList.add(20);
        arrayList.add(30);
        arrayList.add(40);
        System.out.println("修改前:");
        System.out.println("arrayList:"+arrayList);

        List<Integer> list = arrayList.subList(1,3);
        System.out.println("list:"+list);

        list.set(0,999);
        list.set(0,888);

        System.out.println("修改后:");
        System.out.println("arrayList:"+arrayList);
        System.out.println("list:"+list);


    }

为什么对截取后的空间进行数据的修改?原线性表的内容也会发生同样的改变?

  • 原因解释

截取后的变量,依然指向同一块空间;当修改的时候,修改的依然是原数组的内容

4.remove方法

(1)作用:删除线性表中的一个元素,并返回它的值

四.ArrayList的遍历方式

在ArrayListd的方法中,没有可以直接用来遍历的方法,但是我们可以通过自己编写的代码来遍历,如for循环等等,下面一一介绍

  • 最常规的方式,直接打印
  public static  void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(5);
        arrayList.add(2);
        arrayList.add(0);
        System.out.println(arrayList);
}

1.for循环遍历

(1)常规for循环

求得该线性表的元素个数即可

public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(5);
        arrayList.add(2);
        arrayList.add(0);
        for (int i = 0; i < arrayList.size(); i++) {
            System.out.print(arrayList.get(i)+" ");
        }
    }

(2)加强for循环

for循环中也可可以这么写:int x : arrayList(那么里面的数据类就是发生了拆箱的操作)

 public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(5);
        arrayList.add(2);
        arrayList.add(0);
        for (Integer x:arrayList) {
            System.out.print(x+" ");
        }
    }

2.使用迭代器遍历

 可以使用迭代器遍历的前提是该集合实现了Iterable,载使用前,需要先获取线性表的迭代器

(1)从前往后迭代:Iterator接口

 public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(5);
        arrayList.add(2);
        arrayList.add(0);
        Iterator<Integer> it = arrayList.iterator();//获取到线性表的迭代器
        //开始遍历
        while(it.hasNext()) {
            System.out.print(it.next()+" ");//每次打印它的下一个
        }
    }

 图解:

(2)从前往后遍历:ListIterator接口

 public static  void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(5);
        arrayList.add(2);
        arrayList.add(0);
        ListIterator<Integer> it2 = arrayList.listIterator();
        while(it2.hasNext()) {
            System.out.print(it2.next()+" ");
        }
    }

与Iterator接口的关系:继承关系

(3)从后往前遍历:ListIterator接口(加参数即可)

 public static  void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(5);
        arrayList.add(2);
        arrayList.add(0);
        ListIterator it3 = arrayList.listIterator(arrayList.size());//让迭代器指向最后一个元素后面
        while (it3.hasPrevious()) {
            System.out.print(it3.previous()+" ");//打印前一个
        }
    }


本次的介绍就到这里了,小伙伴们快去试试吧

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

react-photo-view 的介绍、安装、使用。

目录 基本介绍 安装 使用 基本介绍 react-photo-view 是一个基于 React 的图片查看器组件&#xff0c;用于在网页上展示和浏览图片。该组件提供了用户友好的界面和交互&#xff0c;可以轻松地在应用程序中集成并使用。 支持触摸手势&#xff0c;拖动/平移/物理效果滑动…

【vtkWidgetRepresentation】第七期 vtkImplicitPlaneRepresentation

很高兴在雪易的CSDN遇见你 前言 本文分享vtkImplicitPlaneRepresentation源码剖析&#xff0c;及相关的实例&#xff0c;该接口主要用于切割交互&#xff0c;希望对各位小伙伴有所帮助&#xff01; 感谢各位小伙伴的点赞关注&#xff0c;小易会继续努力分享&#xff0c;一起…

利用lammps模拟不同压头半径对单晶铝纳米压痕的影响

2.1.问题描述 纳米压痕是确定金属材料特性的最广泛使用的方法之一。分子动力学&#xff08;MD&#xff09;模拟是一种强大的工具&#xff0c;可以研究纳米压痕过程中原子尺度上的材料行为&#xff0c;并深入了解材料的塑性变形。本工作采用单晶铝作为原材料&#xff0c;旨在为…

虾皮免费分析工具:了解市场趋势、优化产品和店铺运营

在如今竞争激烈的电商市场中&#xff0c;了解市场趋势、优化产品和店铺运营对于卖家来说至关重要。虾皮&#xff08;Shopee&#xff09;作为一家知名的电商平台&#xff0c;为卖家提供了一些免费的分析工具&#xff0c;帮助他们更好地了解市场情况并做出明智的决策。本文将介绍…

人工智能教程(三):更多有用的 Python 库

目录 前言 推荐 JupyterLab 入门 复杂的矩阵运算 其它人工智能和机器学习的 Python 库 前言 在本系列的上一篇人工智能教程&#xff08;二&#xff09;&#xff1a;人工智能的历史以及再探矩阵中&#xff0c;我们回顾了人工智能的历史&#xff0c;然后详细地讨论了矩阵。在…

导入PR的视频画面是黑屏的怎么办?

在现代视频编辑领域中&#xff0c;越来越多的人使用Adobe Premiere Pro来编辑和制作视频&#xff0c;但是在某些情况下&#xff0c;用户可能需要透明背景的视频进行创作&#xff0c;那么如何创作透明背景的视频呢&#xff1f; 要制作具有透明背景的视频&#xff0c;我们需要使…

深度探索Linux操作系统 —— 构建initramfs

系列文章目录 深度探索Linux操作系统 —— 编译过程分析 深度探索Linux操作系统 —— 构建工具链 深度探索Linux操作系统 —— 构建内核 深度探索Linux操作系统 —— 构建initramfs 文章目录 系列文章目录前言一、为什么需要 initramfs二、initramfs原理探讨三、构建基本的init…

在Windows 11中,至少有四种方法可以创建用户

本文介绍如何在Windows11上添加另一个用户(或多个用户)。 使用设置添加其他用户 这是创建新用户的“正常”方式。这是一个简单的过程,允许你添加Microsoft、本地或家庭帐户。 添加Microsoft或本地帐户 按照以下步骤将Microsoft帐户添加到Windows 11或创建新的本地用户。…

论文阅读:PointCLIP: Point Cloud Understanding by CLIP

CVPR2022 链接&#xff1a;https://arxiv.org/pdf/2112.02413.pdf 0、Abstract 最近&#xff0c;通过对比视觉语言预训练(CLIP)的零镜头学习和少镜头学习在2D视觉识别方面表现出了鼓舞人心的表现&#xff0c;即学习在开放词汇设置下将图像与相应的文本匹配。然而&#xff0c;…

实现手机扫码——扫描识别路由器参数

有个应用是批量自动检测无线路由器&#xff0c;检测前需要自动登录路由器的管理界面进行设置&#xff0c;如设置wifi参数、连接模式&#xff0c;或者恢复出厂设置等。进入管理界面的登录用户名是admin&#xff0c;密码则各不相同。此外也需要知道路由器的MAC地址&#xff0c;因…

Qt基础-程序打包发布方法

本文讲解Qt程序打包发布方法。 一、使用Qt自带的windeployqt 生成可运行的包 准备将Qt生成的exe拷入到单独的文件夹,并进行命名,本文命名为packDemorun,并将文件放到D盘(自己随意放置) 1、找到Qt自带的命令终端 2、启动命令终端 3、输入:cd /d D:\packDemorun,进入文…

质量工程化,交付快速化

质量和速度之间权衡让人很难取舍&#xff0c;而通过推进质量工程&#xff0c;以系统化的方式识别和优化系统痛点&#xff0c;可以帮助团队构建既快又好的精益软件生产系统。原文: Quality Engineered, Speed Delivered 所有人都想要更快的速度。 但需要解决复杂问题: 权衡质量会…

小程序时代的机遇:开发成功的知识付费平台

知识付费平台不仅为知识创作者提供了广阔的变现渠道&#xff0c;同时也为用户提供了更为个性化、精准的学习体验。本篇文章&#xff0c;小编将为大家讲解知识付费小程序开发相关的知识。 一、小程序时代的背景 知识付费作为小程序领域中的“大热门”&#xff0c;有着非常高的…

整数在内存中的存储

整数和浮点数在内存中的存储方式是不一样的&#xff0c;今天&#xff0c;我们来具体学习一下 文章目录 整数在内存中的存储浮点数在内存中的存储 整数在内存中的存储 我们在之前就已经了解过了整数有原码&#xff0c;反码&#xff0c;补码的形式&#xff0c;这三种方式都是二进…

springboot 集成Dubbo2.7.8 ,连接zookeeper 提示错误 zookeeper not connected

Dubbo 连接zookeeper时&#xff0c;提示“zookeeper not connected” java.lang.IllegalStateException: zookeeper not connectedat org.apache.dubbo.remoting.zookeeper.curator.CuratorZookeeperClient.<init>(CuratorZookeeperClient.java:83) ~[dubbo-2.7.8.jar:2.…

【每周一测】Java阶段四第二周学习

目录 1、在MyBatis中&#xff0c;当实体类中的属性名和表中的字段名不一样&#xff0c;除了&#xff08; &#xff09;都可以实现属性和数据的映射。 2、下列数组定义及赋值&#xff0c;错误的是&#xff08; &#xff09; 3、关于会话跟踪以下说法错误的&#xff08; &…

C++ Qt开发:Qt的安装与配置

Qt是一种C编程框架&#xff0c;用于构建图形用户界面&#xff08;GUI&#xff09;应用程序和嵌入式系统。Qt由Qt公司&#xff08;前身为Nokia&#xff09;开发&#xff0c;提供了一套跨平台的工具和类库&#xff0c;使开发者能够轻松地创建高效、美观、可扩展的应用程序。其被广…

多线程(进阶一:锁策略)

一、乐观锁和悲观锁 二、轻量级锁和重量级锁 三、自旋锁和挂起等待锁 四、普通互斥锁和读写锁 五、公平锁和非公平锁 六、可重入锁和不可重入锁 七、synchronized和Linux的mutex锁的简单比较 八、synchronized的自适应 一、乐观锁和悲观锁 乐观锁&#xff1a;在加锁之前…

启动游戏出现concrt140.dll错误的8种解决方法

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是找不到concrt140.dll文件。这个错误通常会导致程序无法正常运行&#xff0c;给用户带来困扰。本文将介绍找不到concrt140.dll无法继续执行代码的8个方法&#xff0c;同时探讨concrt140.dll丢…

【活动】内容运营活动,你做对了吗?

内容运营活动&#xff0c;首先应该确认本次活动的主题&#xff0c;明确目标受众&#xff0c;分析这类用户的使用场景&#xff0c;感兴趣的话题等&#xff0c;结合市场的热点&#xff0c;探讨活动的形式&#xff0c;过程节点&#xff0c;活动奖励等内容&#xff08;头脑风暴形式…