这篇文章我是这样安排的---》首先对ArrayList类做一个介绍-》其次对ArrayList进行模拟实现-》最后我们将ArrayList的源码几个重要的点讲一下。

给大家分享个宝藏这里可以阅读ArrayList的详细源码讲解:ArrayList源码&扩容机制分析 | JavaGuide

本篇文章最后讲解ArrayList源码时候会参考这篇文章进行讲解。好,我们一起来学习ArrayList吧~~~~~

目录

ArrayList类介绍

ArrayList的模拟实现

ArrayList的类成员

toString方法或者display方法(数组元素的打印)

增加元素方法add(int data)

在某一个位置增加元素add方法add(int index,int data)

判断数组中是否包含某一个元素-->contains方法

找到元素的位置indexOf方法

获取index位置的元素get方法

给index位置更新元素set方法

删除数组中的元素remove方法

size()方法

clear()方法清空顺序表

ArrayList的构造方法

ArrayList的扩容机制


ArrayList类介绍

ArrayList是List接口实现的类,也就是这个类实现了List接口,同时还有一个重要的类那就是LinkedList,这两个类都是实现了List接口并且非常重要。

ArrayList通过看源码我们就知道ArrayList底层是一个动态数组,可以动态增容,如果数组元素满了,那就创建一个1.5倍的这样的数组,然后把旧数组利用copyOf方法将其进行拷贝到新的数组中然后返回新的数组。

ArrayList的模拟实现

ArrayList的类成员

首先ArrayList是一个动态数组,我们要有一个数组。

还有一个问题,既然是动态的那怎么才能实现呢?我们先来举个例子,比如个数组开辟了10个空间,我放入了元素0,0,0,0,0,9,那它是怎么计算的呢?没错我们就是需要一个计数器来计算数组中到底有多少个元素,也就是数组中元素的有效个数。当我们添加或者删除元素,这个有效个数就要执行相应的操作。

所以,在实现一个ArrayList类中我们要有两个最核心的东西,那就是一个数组,一个数组的有效个数。还有其他的就是ArrayList所需要实现的核心方法。

    private int usedSize =0;public static final int DEFAULT_CAPACITY =10;private int[] elem;public MyArrayList() {this.elem = new int[DEFAULT_CAPACITY];this.usedSize =0;}

我们创建一个数组elem和有效个数usedSize,实现了一个构造方法对数组容量和有效个数进行相应的初始化,我们将这个数组容量初始化为10,有效个数初始化为0;

toString方法或者display方法(数组元素的打印)

我们先来实现一个简单地方法也就是将这个数组的元素打印出来,当然我们可以自己实现一个display方法也可以重写toString方法进行打印数组元素。

重写toString方法:

    @Overridepublic String toString() {StringBuilder sb = new StringBuilder();sb.append("[");for(int i =0;i<this.size();++i) {sb.append(elem[i]);if(i!=this.size()-1) {sb.append(",");}}sb.append("]");return sb.toString();}

实现display()方法:

    // 打印顺序表public void display() {for(int i =0;i<this.usedSize;++i) {System.out.print(this.elem[i]+" ");}System.out.println();}

思路很简单:就是遍历这个数组打印对应的元素即可。

增加元素方法add(int data)

首先add方法我们要考虑的

  • 数组是否满?如果满我们就需要增容
    // 新增元素,默认在数组最后新增public void add(int data) {//增加元素前要先判断顺序表是否需要增容if(isFull()) {this.elem = Arrays.copyOf(this.elem,2*this.elem.length);}//开始增加元素this.elem[this.usedSize] = data;this.usedSize++;}
  • isfull()

只需要检查数组是否满?如果满了就需要进行增容,如果不满就可以增加元素了。

//检查顺序表是否满?如果满了就需要增容private Boolean isFull() {return this.usedSize==this.elem.length;}
  • 增加元素:

增加元素就是将元素放在对应usedSize下标,此时usedSize既充当数组中的有效个数又充当了待放入元素的下标,可谓是两全其美啊。

在某一个位置增加元素add方法add(int index,int data)

需要考虑如下几点:

  • 数组是否满??
  • index位置合不合法?
  • 数组是否为空数组(其实这个可以不需要)
  • 增加元素
    // 在 pos 位置新增元素public void add(int pos, int data) throws PosIndexOfBoundsException, SqListEmptyException {//在pos位置添加元素要判断pos位置的合法性if(!checkInAdd(pos)) {throw new PosIndexOfBoundsException("pos位置不合法");}//检查顺序表是否为空if(isEmpty()) {throw new SqListEmptyException("顺序表为空,无法新增pos位置元素");}//检查顺序表是否满了?if(isFull()) {this.elem = Arrays.copyOf(this.elem,2*this.elem.length);}//在pos位置新增元素for(int i =this.usedSize-1;i>=pos;--i) {this.elem[i+1] = this.elem[i];}//此时pos位置已经是空着的,放入元素this.elem[pos] = data;this.usedSize++;}
  • isEmpty()
    //检查顺序表是否为空private Boolean isEmpty() {return this.usedSize==0;}
  • checkInAdd()检查下标是否合法
    //检查pos位置的合法性private Boolean checkInAdd(int pos) {if(pos<0||pos>this.usedSize) {return false;}return true;}
  • 数组是否满?

    //检查顺序表是否满?如果满了就需要增容private Boolean isFull() {return this.usedSize==this.elem.length;}
  • 增加元素

我们要先将这个index位置给空出来才能放入元素,所以我们从数组最后一个元素(注意可不是数组最后一个位置),开始挪动数据,将本位置的数据移动到本位置的下一个位置。最后将index位置空出来,我们就将这个位置放入data元素就可以了。

判断数组中是否包含某一个元素-->contains方法

    // 判定是否包含某个元素public boolean contains(int toFind) {for(int i =0;i<this.usedSize;++i) {if(elem[i]==toFind) {return true;}}return false;}

思路:遍历数组看是否有这个元素,如果有返回true,没有返回false。

找到元素的位置indexOf方法

    // 查找某个元素对应的位置public int indexOf(int toFind) {for(int i =0;i<this.usedSize;++i) {if(elem[i]==toFind) {return i;}}return -1;}

思路:找到对应的元素返回对应的下标即可。

获取index位置的元素get方法

  • 需要判断index位置是否合法
    // 获取 pos 位置的元素public int get(int pos) throws PosIndexOfBoundsException {if(pos<0&&pos>=this.usedSize) {throw new PosIndexOfBoundsException("获取pos位置的元素时pos位置不合法");}return this.elem[pos];}

思路:找到对应下标,返回对应元素。

给index位置更新元素set方法

    // 给 pos 位置的元素设为 valuepublic void set(int pos, int value) throws PosIndexOfBoundsException, SqListEmptyException {if(!checkInAdd(pos)) {throw new PosIndexOfBoundsException("pos位置不合法");}if(isEmpty()) {throw new SqListEmptyException("顺序表为空,无法新增pos位置元素");}this.elem[pos] = value;}

只要有位置就需要判断其合法性,还要判断一下数组是否为空数组,然后将index位置的元素覆盖成新的元素value。

删除数组中的元素remove方法

    //删除第一次出现的关键字keypublic void remove(int toRemove) throws SqListEmptyException {//第一步要先检查这个顺序表是否为空if(isEmpty()) {throw new SqListEmptyException("顺序表为空,无法删除元素");}//检查这个要删除的元素是否存在int ret = indexOf(toRemove);if(ret==-1) {System.out.println("你要删除的元素不存在顺序表中,无法删除!!!");return;}for(int i =ret;i<this.usedSize-1;++i) {this.elem[i] = this.elem[i+1];}this.usedSize--;}
  • 还是要判断数组是否为空数组,如果是空数组就不能删除元素。
  • 找到要删除元素对应下标,是否存在这个元素。
  • 从要删除元素的下标开始,对删除的元素的位置进行覆盖即可。
  • 同时有效个数--

size()方法

    // 获取顺序表长度public int size() {return this.usedSize;}

将有效长度返回即可。

clear()方法清空顺序表

只要将其有效个数设置为0即可。

    // 清空顺序表public void clear() {this.usedSize = 0;}

ArrayList的构造方法

ArrayList的构造方法有三种:

  • 第一种就是不带参数的构造方法:

通过读源码和源码注释可以知道:数组默认容量是0(也就是没有添加元素的时候数组容量为0),而当我们添加了元素之后数组容量就变为了10;

  • 第二种是带参数为初始容量的构造方法

参数为initialCapacity,意思是用户可以自定义这个数组的容量大小,如果参数为0,这个数组就为空,其他情况非法报异常。

  • 第三种构造方法

参数为E这个类型参数的子类或者本身。举个例子:

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

我们可以将这个list1作为类型参数传递,这个list2就拥有了list1的元素。

ArrayList的扩容机制

add方法-》ensureCapacityInternal()当 要 add 进第 1 个元素时,minCapacity 为 1,在 Math.max()方法比较后,minCapacity 为 10。)-》直到添加第 11 个元素,minCapacity(为 11)比 elementData.length(为 10)要大。进入 grow 方法进行扩容。-》int newCapacity = oldCapacity + (oldCapacity >> 1),所以 ArrayList 每次扩容之后容量都会变为原来的 1.5 倍左右(oldCapacity 为偶数就是 1.5 倍,否则是 1.5 倍左右)!-》

结论: ArrayList 每次扩容之后容量都会变为原来的 1.5 倍左右(oldCapacity 为偶数就是 1.5 倍,否则是 1.5 倍左右。

ArrayList接口练习扑克牌:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;class Poker {private int rank;//扑克牌的排行private String suit;//扑克牌的花色public Poker(int rank, String suit) {this.rank = rank;this.suit = suit;}public int getRank() {return rank;}public void setRank(int rank) {this.rank = rank;}public String getSuit() {return suit;}public void setSuit(String suit) {this.suit = suit;}@Overridepublic String toString() {return "Poker{" +"rank=" + rank +", suit='" + suit + '\'' +'}';}
}public class TestDemo {//买牌public static final String Suit[]={"♠", "♥", "♣", "♦"};public static void buyPoker(List<Poker> pokerList) {//首先产生1-13个数字,然后每一个数字对应着四种花色for(int i =1;i<=13;++i) {for(int j=0;j<4;++j) {Poker poker = new Poker(i,Suit[j]);pokerList.add(poker);}}}public static void SwapPoker(List<Poker>pokerList,int i,int index) {//得到i下标的牌,Poker tmp = pokerList.get(i);//将i下标的位置设置为index下表的牌pokerList.set(i,pokerList.get(index));//再把i下标这个牌放到index的位置上去pokerList.set(index,tmp);}private static List<Poker> shuffle(List<Poker> pokerList) {//主要是将买好的牌进行打乱for(int i = pokerList.size()-1;i>0;--i) {//产生随机数Random random = new Random();int index = random.nextInt(i);//得到这个随机位置的牌SwapPoker(pokerList,i,index);}return pokerList;}public static void main(String[] args) {//实现一副扑克牌List<Poker> pokerList = new ArrayList<>();buyPoker(pokerList);//已经买好的牌System.out.println(pokerList);List<Poker> pokers =shuffle(pokerList);//洗过的牌System.out.println(pokers);//接下来三人开始斗地主List<Poker> hand1 = new ArrayList<>();List<Poker> hand2 = new ArrayList<>();List<Poker> hand3 = new ArrayList<>();List<List<Poker>> hands = new ArrayList<>();hands.add(hand1);hands.add(hand2);hands.add(hand3);//接下来开始轮流发牌,每个人只有5张牌,一共法给3个人for(int i=0;i<5;++i) {for(int j =0;j<3;++j) {//先从桌子上摸一张牌,然后给一个人Poker card = pokers.remove(0);hands.get(j).add(i,card);}}System.out.println(hand1);System.out.println(hand2);System.out.println(hand3);}
}

【JAVA 数据结构】 JAVA实现动态数组相关推荐

  1. 2021-9-下旬 数据结构-线性表-动态数组-java代码实现

    信管的数据结构讲的太水了,遂重学(看的网课:恋上数据结构与算法,讲的very good),为算法学习打基础(都大三了还在打基础),顺便在leetcode上跟进一些相关的题,记录在这里,这里最方便复习 ...

  2. java动态数组的实现的_Java实现数据结构之【动态数组】

    数组是学习编程语言时较先接触到的一种数据结构,本章基于Java的静态数组实现动态数组,并进行简单的复杂度分析 数组相信各位都知道,那什么是动态数组呢?我们定义一个数组后,一般长度会直接定义好,如果数组 ...

  3. Java数据结构和算法:数组、单链表、双链表

    1. 概要 线性表是一种线性结构,它是具有相同类型的n(n≥0)个数据元素组成的有限序列.本章先介绍线性表的几个基本组成部分:数组.单向链表.双向链表:随后给出双向链表的C.C++和Java三种语言的 ...

  4. java中的arrayList(动态数组)与静态数组

    首先,有时用数组时,常把静态数组和动态相混淆,今天来区分一下: 先写一下java中静态数组, 一维数组的声明方式: type var[]; 或type[] var; 声明数组时不能指定其长度(数组中元 ...

  5. java 数据结构详解,数组,集合,HashMap

    数组的特性: 数组在内存中是一块连续的存储单元存储起来的,声明数组的时候我们必须声明其长度,这样才会为我们声明一个连续的存储区域. 这种存储方式造成我们想要往数组中存储一个数据时那么其后面各个元素都要 ...

  6. 数据结构基础之动态数组

    动态数组 数组的局限性 目前为止所实现的数组类,有一个非常严重的局限性,就是这个数组实际使用的还是一个静态数组,内部容量有限.在实际使用的时候,我们往往无法预估要在这个数组中存入多少个元素. 解决方案 ...

  7. golang数据结构初探之动态数组slice

    动态数组slice slice 又称动态数组,依托于数组实现,可以方便的进行扩容和传递,实际使用时比数组更灵活.但正是因为灵活,实际使用时更容易出错,避免出错的最好方法便是了解其实现原理. 特性速览 ...

  8. 基于java的数据结构学习——泛型动态数组的封装

    public class Array<E> {private E[] data;private int size;// 构造函数public Array(int Capacity){dat ...

  9. Java数据结构和算法( 二 ) ## 数组

    目录 数组综述 Java中的数组 创建数组 访问数组 初始化数组 有序数组 线性查找 二分查找 有序数组的优缺点 大O表示法(order of) 为什么不用数据解决一切 - 小结 数组综述 数组是最广 ...

  10. Java数据结构和算法的数组

    阵列的功能: 1.固定大小 2.相同的数据类型 3. 4.数据项可反复 Java数据类型:基本类型(int和double)和对象类型.在很多编程语言中.数组也是基本类型.但在Java中把它们当作对象来 ...

最新文章

  1. 单词转换(map对象)
  2. 全球第三位艾滋病痊愈者出现,靠脐带血干细胞新疗法抵抗病毒,此前已患病9年...
  3. Ubuntu报错:sudo 无法解析的主机
  4. Micropython Turnipbit自动窗帘模拟系统
  5. javascript学习系列(3):数组中的foreach方法
  6. SQL ROUND函数用法
  7. 无法读取项目文件 .csproj
  8. JavaScript学习笔记 -- ES6学习(三) 变量的解构赋值
  9. BN层对神经网络神经元数据分布的影响
  10. google protobuf windows下环境配置
  11. leach协议c++代码_入门教程4:教你STM32F407标准库移植机智云代码(控制LED灯)
  12. java ssh2连接_通过JCraft的jsch包基于SSH2协议实现连接linux服务器提供终端操作的java工具实现类SftpUtil...
  13. 面试中最常见的10个经典问题,答对了通过率提高50%,快来抄答案!
  14. WorkPlus助力“深i企”打造移动数字化底座
  15. openssl 1.0.2k-fips 升级到 openssl-3.0.3
  16. 程序员520❤七夕情人节表白代码Html+Js+Css花瓣相册网页模板❤程序员表白必备
  17. 北斗通讯协议4.0 java_北斗4.0协议讲解.doc
  18. 什么是 SAP Support Package Stack
  19. 2022-12- 05 网工进阶(三十七)MPLS--基本概念、转发过程、基本配置、配置静态LSR
  20. python模块之 paramiko

热门文章

  1. 内存条hyperx_一键开启内存条最高效能 HyperX雷电系列3733MHz内存条评测
  2. 3dmax渲染出来的图不清晰?
  3. 认识电脑键盘附加快捷键
  4. [渝粤教育] 长沙航空职业技术学院 液压与气动技术 参考 资料
  5. 基于STM32的四位TM1637完整程序
  6. 【matplotlib笔记】sin图像与cos图像
  7. .NET(c#) 移动APP开发平台之Smobiler开发
  8. DevOps落地实践:通讯行业系列:NTT COMWARE之Devaas
  9. 牛顿插值法 matlab程序计算方法,(最新整理)牛顿插值法matlab程序
  10. 科学计算机怎么直接显示10的多少次方,科学计算器怎么开n次方