首页 > 编程知识 正文

手机查看jdk源码(arraylist的方法有哪些)

时间:2023-05-05 06:50:21 阅读:90006 作者:1630

在Java集合中,必须首先从ArrayList开始。 本来,ArrayList可以说是集合中最常用的类,所以我想没有之一。

ArrayList实现了List接口,并基于数组实现。 众所周知,数组的大小是固定的,如果在创建时指定大小,就无法进一步调整。 如果数组已满,则无法添加更多元素。 ArrayList是数组的绝佳替代方案,提供比数组更丰富的预定义方法,根据元素的数量自动调整大小,非常灵活。

准备将元素55添加到ArrayList的第四个位置(下标为3 )。

ArrayList中的第五个以后的元素会向后移动。

准备从数组列表中删除23。

此时,下标为7、8、9的要素向前移动。

01、如何创建一个 ArrayList

数组列表=网络数组列表(; 可以使用以上语句创建字符串类型的ArrayList。 ArrayList中的元素类型受尖括号限制,如果尝试添加其他类型的元素,将会导致编译错误。 )更简单的写法如下。

liststring a list=新阵列列表(; 由于ArrayList实现了List接口,因此aList变量的类型可以是List类型; 可以不在new关键字声明之后的尖括号中指定元素类型。 因为编译器可以根据前面尖括号内的类型智能地估计。

如果清楚地知道ArrayList中元素的数量,也可以在创建时指定初始大小。

liststringalist=新阵列列表(20; 这样做的好处是,可以有效避免添加新元素时不必要的扩展。 但是,由于通常很难确定ArrayList中元素的数量,因此通常不指定初始大小。

02、向 ArrayList 中添加一个元素

可以使用add ()方法将元素添加到ArrayList中。 如果未指定下标,则缺省情况下将其添加到末尾。

笑嘻嘻的羊; 感兴趣的合作伙伴可以尝试查看add (方法的源代码。 这是在添加元素时grow ) )方法来扩展。 这是面试官特别喜欢考察的重点。

以下是add(e )方法的源代码。

公共布告栏安卓{

模具计数;

add (电子元件数据,大小);

返回真;

}调用了专用的add(e,object [ ]元素数据,int s )方法。

私有元素数据(e,对象) {

if (s==元素数据.长度) )。

元素数据=grow (;

元素数据=e;

size=s 1;

然后调用了非常重要的grow (最小容量)方法。

私有对象(最小容量)。

int oldCapacity = elementData.length; if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { int newCapacity = ArraysSupport.newLength(oldCapacity, minCapacity - oldCapacity, /* minimum growth */ oldCapacity >> 1 /* preferred growth */); return elementData = Arrays.copyOf(elementData, newCapacity); } else { return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)]; } }

如果创建 ArrayList 的时候没有指定初始大小,那么 ArrayList 的初始大小就是 DEFAULT_CAPACITY:

private static final int DEFAULT_CAPACITY = 10;

可以容纳 10 个元素。

还可以通过 add(int index, E element) 方法把元素添加到指定的位置:

alist.add(0, "tmddw");

add(int index, E element) 方法的源码如下:

public void add(int index, E element) { rangeCheckForAdd(index); modCount++; final int s; Object[] elementData; if ((s = size) == (elementData = this.elementData).length) elementData = grow(); System.arraycopy(elementData, index, elementData, index + 1, s - index); elementData[index] = element; size = s + 1; }

该方法会调用到一个非常重要的本地方法 System.arraycopy(),它会对数组进行复制(要插入位置上的元素往后复制,参照文章一开头提到的两张图片)。

03、更新 ArrayList 中的元素

可以使用 set() 方法来更改 ArrayList 中的元素,需要提供下标和新元素。

alist.set(0, "dqdddd);

原来 0 位置上的元素为“tmddw”,现在将其更新为“风趣的黄蜂。

来看一下 set() 方法的源码:

public E set(int index, E element) { Objects.checkIndex(index, size); E oldValue = elementData(index); elementData[index] = element; return oldValue; }

该方法会先对指定的下标进行检查,看是否越界,然后替换新值并返回旧值。

04、删除 ArrayList 中的元素

remove(int index) 方法用于删除指定下标位置上的元素,remove(Object o) 方法用于删除指定值的元素。

alist.remove(1); alist.remove("dqdddd);

先来看 remove(int index) 方法的源码:

public E remove(int index) { Objects.checkIndex(index, size); final Object[] es = elementData; @SuppressWarnings("unchecked") E oldValue = (E) es[index]; fastRemove(es, index); return oldValue; }

该方法返回要删除的元素,真正的删除操作在 fastRemove(es, index) 方法中。

再来看 remove(Object o) 方法的源码:

public boolean remove(Object o) { final Object[] es = elementData; final int size = this.size; int i = 0; found: { if (o == null) { for (; i < size; i++) if (es[i] == null) break found; } else { for (; i < size; i++) if (o.equals(es[i])) break found; } return false; } fastRemove(es, i); return true; }

该方法通过 break label 的方式找到要删除元素(null 的时候使用 == 操作符判断,非 null 的时候使用 equals() 方法,意味着如果有相同元素时,删除第一个)的下标,然后调用 fastRemove() 方法。

既然都调用了 fastRemove() 方法,那就继续来跟踪一下源码:

private void fastRemove(Object[] es, int i) { modCount++; final int newSize; if ((newSize = size - 1) > i) System.arraycopy(es, i + 1, es, i, newSize - i); es[size = newSize] = null; }

当删除的是末尾的元素时,不需要复制数组,直接把末尾的元素赋值为 null 即可;否则的话,就需要调用 System.arraycopy() 对数组进行复制。参照文章一开头提到的第三张、第四张图片。

05、查找 ArrayList 中的元素

如果要正序查找一个元素,可以使用 indexOf() 方法;如果要倒序查找一个元素,可以使用 lastIndexOf() 方法。

alist.indexOf("微笑的羊); alist.lastIndexOf("微笑的羊);

来看一下 indexOf() 方法的源码:

public int indexOf(Object o) { return indexOfRange(o, 0, size); } int indexOfRange(Object o, int start, int end) { Object[] es = elementData; if (o == null) { for (int i = start; i < end; i++) { if (es[i] == null) { return i; } } } else { for (int i = start; i < end; i++) { if (o.equals(es[i])) { return i; } } } return -1; }

如果元素为 null 的时候使用“==”操作符,否则使用 equals() 方法——该方法不是 null 安全的。

lastIndexOf() 方法和 indexOf() 方法类似,不过遍历的时候从最后开始。

contains() 方法可以判断 ArrayList 中是否包含某个元素,其内部调用了 indexOf() 方法:

public boolean contains(Object o) { return indexOf(o) >= 0; }

如果 ArrayList 中的元素是经过排序的,就可以使用二分查找法,效率更快。

Collections 类的 sort() 方法可以对 ArrayList 进行排序,该方法会按照字母顺序对 String 类型的列表进行排序。如果是自定义类型的列表,还可以指定 Comparator 进行排序。

List<String> copy = new ArrayList<>(alist); copy.add("a"); copy.add("c"); copy.add("b"); copy.add("d"); Collections.sort(copy); System.out.println(copy);

输出结果如下所示:

[a, b, c, d] 1

排序后就可以使用二分查找法了:

int index = Collections.binarySearch(copy, "b");

06、最后

关于 ArrayList,就先介绍这么多吧,通过源码的角度,我想小伙伴们一定对 ArrayList 有了更深刻的印象。

简单总结一下 ArrayList 的时间复杂度,方便后面学习 LinkedList 时作为一个对比。

1)通过下标(也就是 get(int index))访问一个元素的时间复杂度为 O(1),因为是直达的,无论数据增大多少倍,耗时都不变。

2)添加一个元素(也就是 add())的时间复杂度为 O(1),因为直接添加到末尾。

3)删除一个元素的时间复杂度为 O(n),因为要遍历列表,数据量增大几倍,耗时也增大几倍。

4)查找一个未排序的列表时间复杂度为 O(n),因为要遍历列表;查找排序过的列表时间复杂度为 O(log n),因为可以使用二分查找法,当数据增大 n 倍时,耗时增大 logn 倍(这里的 log 是以 2 为底的,每找一次排除一半的可能)

作者:沉默王二

原文链接:https://blog.csdn.net/风趣的萝莉_gee/article/details/107197446

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。