0


【Java基础】Java8集合[ArrayList 常用方法讲解](源码分析+底层原理)

CSDN话题挑战赛第2期
参赛话题:学习笔记

在这里插入图片描述
在这里插入图片描述

Java8集合:ArrayList


一、前言

集合主要分为

Collection接口

Map接口

两类,而

ArrayList

就是

Collection

接口中

List

子接口的实现类…

在上一篇文章中,我们通过ArrayList实现类的源码,了解到了其中的属性,比较印象深刻的应该是ArrayList集合底层由一个

Object[]

数组实现,且可以存放包括

null

在内的所有元素。

而在这篇文章中,我们将讲解集合中

ArrayList

实现类的

方法


二、集合ArrayList方法

1.构造方法

①空参构造器

源码

publicArrayList(){this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}

这是源码中的空参构造器,当我们创建ArrayList对象,没有设置参数传递,也就是默认情况下,存储数据的数组

elementData

是一个长度为0的空数组。

List list = new ArrayList();

②带参构造器

源码

publicArrayList(int initialCapacity){if(initialCapacity >0){this.elementData =newObject[initialCapacity];}elseif(initialCapacity ==0){this.elementData = EMPTY_ELEMENTDATA;}else{thrownewIllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);}}

当我们创建ArrayList对象,且设置了传入参数,即指定了初始大小的时候,存储数据的数组

elementData

初始大小就变成了我们指定的初始大小了。

List list = new ArrayList(0);

2.grow方法

源码

privatevoidgrow(int minCapacity){// overflow-conscious codeint oldCapacity = elementData.length;int newCapacity = oldCapacity +(oldCapacity >>1);if(newCapacity - minCapacity <0)
            newCapacity = minCapacity;if(newCapacity - MAX_ARRAY_SIZE >0)
            newCapacity =hugeCapacity(minCapacity);// minCapacity is usually close to size, so this is a win:
        elementData =Arrays.copyOf(elementData, newCapacity);}

集合的扩容机制:

ArrayList集合的底层数组,在扩容的时候会用到grow方法,我们从源码中看到

newCapacity = oldCapacity + (oldCapacity >> 1);

相当于:新的容量 = 旧的容量 + 旧的容量 / 2;

所以

ArrayList

每次扩容都是扩容为

1.5

倍,然后调用Arrays类中的copyOf方法,将元素拷贝到一个新的数组当中…


3.size 方法

源码

publicintsize(){return size;}

代码很简单,就是返回size的值,在上一篇文章中,我们已经熟悉过size属性:

The size of the ArrayList (the number of elements it contains).

返回的size值代表的是集合中存在的元素个数,注意:返回的不是数组的实际空间。

int count = list.size();

4.isEmpty方法

源码

publicbooleanisEmpty(){return size ==0;}

此方法用于判断集合是否为空,方法中使用了上文提及的size属性:

  • 当size == 0 时,代表集合中没有元素,返回true
  • 当size != 0 时,代表集合中存在元素,返回false
boolean a = list.isEmpty();

5.add方法

源码

publicbooleanadd(E e){ensureCapacityInternal(size +1);// Increments modCount!!
        elementData[size++]= e;returntrue;}publicvoidadd(int index,E element){rangeCheckForAdd(index);ensureCapacityInternal(size +1);// Increments modCount!!System.arraycopy(elementData, index, elementData, index +1,
                         size - index);
        elementData[index]= element;
        size++;}privatevoidensureCapacityInternal(int minCapacity){ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));}privatevoidensureExplicitCapacity(int minCapacity){
        modCount++;// overflow-conscious codeif(minCapacity - elementData.length >0)grow(minCapacity);}

使用add方法时:

再插入元素之前,会检查先检查是否需要扩容,之后将传入的元素存放在数组最后一个元素后面的位置。
源码中调用了

ensureCapacityInternal();

方法:
当存储数据的数组elementData为空数组时,就使用默认数组长度去扩容,也就是长度默认为0,只有真正有元素传入,才会使用grow()方法创建长度为10的数组。

element放在最后元素的就没:

list.add(element);

element放在指定下标index的位置上,若位置存在元素,该元素与后续元素向后移动一位,element依旧会放置在指定的index位置上:

list.add(index,element);

6.get方法

源码

publicEget(int index){rangeCheck(index);returnelementData(index);}privatevoidrangeCheck(int index){if(index >= size)thrownewIndexOutOfBoundsException(outOfBoundsMsg(index));}EelementData(int index){return(E) elementData[index];}

将get方法中用到的方法也放进来了,结构不算复杂:

  • 先是使用rangeCheck(index)方法判断是否越界;
  • 之后就是通过传入的index下标获取对应元素;
list.get(index);

7.set方法

源码

publicEset(int index,E element){rangeCheck(index);E oldValue =elementData(index);
        elementData[index]= element;return oldValue;}privatevoidrangeCheck(int index){if(index >= size)thrownewIndexOutOfBoundsException(outOfBoundsMsg(index));}

set方法与上文提到的get方法类似:

  • 先是使用rangeCheck(index)方法判断下标index是否越界;
  • 然后就是将index下标对应的元素替换成传入的element
list.set(index,element);

8.indexOf方法

源码

publicintindexOf(Object o){if(o ==null){for(int i =0; i < size; i++)if(elementData[i]==null)return i;}else{for(int i =0; i < size; i++)if(o.equals(elementData[i]))return i;}return-1;}

在indexOf方法中,我们传入一个元素,方法会返回集合中第一个等于传入元素的元素下标。
方法中运用了循环遍历集合中每个元素来查找是否存在与传入元素相同的元素…

我们还可以注意到,传入的元素包含null,再一次说明了集合可以存储包含null在内的全部元素。

int first_index = list.indexOf(null);

9.lastIndexOf方法

源码

publicintlastIndexOf(Object o){if(o ==null){for(int i = size-1; i >=0; i--)if(elementData[i]==null)return i;}else{for(int i = size-1; i >=0; i--)if(o.equals(elementData[i]))return i;}return-1;}

lastIndexOf方法与上文提到的indexOf方法原理基本一致,但是遍历是

从后往前

的,也就是说返回的是

最后一个

与传入元素相同的

元素下标

int last_index = list.lastIndexOf(null);

10.remove方法

源码

publicEremove(int index){rangeCheck(index);

        modCount++;E oldValue =elementData(index);int numMoved = size - index -1;if(numMoved >0)System.arraycopy(elementData, index+1, elementData, index,
                             numMoved);
        elementData[--size]=null;// clear to let GC do its workreturn oldValue;}

移除此列表中指定位置index上对应的元素。将所有后续元素向左移动一位(从它们的索引中减去1)。

list.remove(index);

到这里,集合ArrayList中较为常用的方法也就讲解完了,同时借助源码,我们还讲解了一些集合的底层实现原理,增加了对集合的认识,很棒,对吗~

在这里插入图片描述

标签: java 开源

本文转载自: https://blog.csdn.net/ebb29bbe/article/details/127070291
版权归原作者 .29. 所有, 如有侵权,请联系我们删除。

“【Java基础】Java8集合[ArrayList 常用方法讲解](源码分析+底层原理)”的评论:

还没有评论