ArrayList源码解析

ArrayList简介:

ArrayList 是list接口的一个常用实现类。它的对象可以认为是一维数组的“类版本”。我们很快就可以看到,ArrayList 对象可以看做是一维数组的改良版本。类似于数组,ArrayList 对象支持元素的随机访问;也就是说,只要给出元素的索引,任何元素的访问时间都是常数。但是同数组不同的是,ArrayList 对象的大小在程序执行的过程中可以自动进行调整,并且ArrayList对象具有在任何索引位置插入和删除对象的方法,而数组如果想要插入和删除对象,则必须要编写代码增加和减少储存空间。

ArrayList方法简介:

首先我们先来看一下ArrayList的所有公共方法。

注:下面方法除构造函数方法外,其他方法皆按照字母顺序排序。

 1 1、public Arraylist()
 2 2、public ArrayList(int initalCapacity)
 3 3、public ArrayList(Collection<? extends E> c)
 4 4、public boolean add(E e)
 5 5、public void add(int index, E element)
 6 6、 public boolean addAll(int index, Collection<? extends E> c)
 7 7、public boolean addAll(Collection<? extends E> c)
 8 8、 public void clear()
 9 9、 public Object clone()
10 10、 public boolean contains(Object o)
11 11、public boolean containsAll(Collection<?> c)
12 12、public void ensureCapacity(int minCapacity)
13 13、public boolean equals(Object o)
14 14、 public void forEach(Consumer<? super E> action)
15 15、public E get(int index)
16 16、public int hashCode()
17 17、 public int indexOf(Object o)
18 18、public boolean isEmpty()
19 19、public Iterator<E> iterator()
20 20、public int lastIndexOf(Object o)
21 21、public ListIterator<E> listIterator()
22 22、public ListIterator<E> listIterator(int index)
23 23、public E remove(int index)
24 24、public boolean remove(Object o)
25 25、public boolean removeAll(Collection<?> c)
26 26、public boolean removeIf(Predicate<? super E> filter)
27 27、 public void replaceAll(UnaryOperator<E> operator)
28 28、public boolean retainAll(Collection<?> c)
29 29、public E set(int index, E element)
30 30、public int size()
31 31、public void sort(Comparator<? super E> c)
32 32、public Spliterator<E> spliterator()
33 33、public List<E> subList(int fromIndex, int toIndex)
34 34、public Object[] toArray()
35 35、public <T> T[] toArray(T[] a)
36 36、public String toString()
37 37、public void trimToSize()

View Code

ArrayList方法解析:

ArrayList类结构关系:

在具体分析Arrayl类的方法之前,我们先看一下ArrayList类的继承关系。
从图中可以看出,ArrayList继承AbstractList类,并且实现了List、RandomAccess、Serializable接口。
其中RandomAccess接口为一个空接口,起到一个标识的作用,如果集合类是RandomAccess的实现,则尽量用for(int i = 0; i < size; i++) 来遍历而不要用Iterator迭代器来遍历,在效率上要差一些。反过来,如果List是Sequence List,则最好用迭代器来进行迭代。 其具体细节在我们在这里就不进行讨论了,感兴趣的同学可以自己去查一查。
Serializable是启用序列化功能的接口,这里也不进行讨论了。
AbstractList继承了AbstractCollection.两者都是抽象类,AbstractCollection提供了Collection接口的一些方法的默认实现,AbstractCollection提供了List接口
的默认实现(个别方法为抽象方法)。

ArrayList类的属性:

 1 //默认容量的大小
 2 private static final int DEFAULT_CAPACITY = 10;
 3
 4 //空数组常量
 5 private static final Object[] EMPTY_ELEMENTDATA = {};
 6
 7 //默认的空数组常量
 8 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
 9
10 //存放元素的数组,从这可以发现ArrayList的底层实现就是一个Object数组
11 transient Object[] elementData;
12
13 //数组中包含的元素个数
14 private int size;
15
16 //数组的最大上限
17 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

View Code


ArrayList的属性非常少,一共就只有这五个。其中:DEFAULT_CAPACITY 代表默认容量的大小,在后面我们可以看到,在像ArrayList对象第一次添
加元素的时候,会将ArrayList的容量设置为默认的容量。EMPTY_ELEMENTDATE和DEFAULTCAPACITY_EMPTY_ELEMENTDATA区别不大。这个在后面
讲构造器的时候会详细讲到。其中最重要的莫过于elementData了,ArrayList所有的方法都是建立在elementData之上。

ArrayList构造函数:

ArrayList一共有三个构造函数,分别为:

 1 public ArrayList(int initialCapacity) {
 2         if (initialCapacity > 0) {
 3             this.elementData = new Object[initialCapacity];
 4         } else if (initialCapacity == 0) {
 5             this.elementData = EMPTY_ELEMENTDATA;
 6         } else {
 7             throw new IllegalArgumentException("Illegal Capacity: "+
 8                                                initialCapacity);
 9         }
10     }
11     public ArrayList() {
12         this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
13     }
14     public ArrayList(Collection<? extends E> c) {
15         elementData = c.toArray();
16         if ((size = elementData.length) != 0) {
17             // c.toArray might (incorrectly) not return Object[] (see 6260652)
18             if (elementData.getClass() != Object[].class)
19                 elementData = Arrays.copyOf(elementData, size, Object[].class);
20         } else {
21             // replace with empty array.
22             this.elementData = EMPTY_ELEMENTDATA;
23         }
24     }

View Code

从构造函数我们可以看出,elementDate默认是一个大小为0的的数组,即DEFAULTCAPACITY_EMPTY_ELEMENTDATA,而
当指定数组长度时,elementData的初始大小就变成了我们所指定的初始大小了。如果我们指定数组的默认长度为0时,
elementDate即为EMPTY_ELEMENTDATA,在这里我们还看不出两者的区别,在后面讲到add方法时,就可以看到两者的不同了。
ArrayList同样可以传入一个Collection,当Collection不为空时,复制该Collection。否则elementDate仍然为EMPTY_ELEMENTDATA。

ArrayList的公共方法:

ArrayList的添加方法:

ArrayList添加单个元素有两个方法,分别为:

 1     public boolean add(E e) {
 2         ensureCapacityInternal(size + 1);  // Increments modCount!!
 3         elementData[size++] = e;
 4         return true;
 5     }
 6     public void add(int index, E element) {
 7         rangeCheckForAdd(index);
 8
 9         ensureCapacityInternal(size + 1);  // Increments modCount!!
10         System.arraycopy(elementData, index, elementData, index + 1,
11                          size - index);
12         elementData[index] = element;
13         size++;
14     }

View Code

add(E e)方法是用来添加一个单个的元素,其调用了私有方法enesureCapacityInternal(size+1).

 1   private void ensureCapacityInternal(int minCapacity) {
 2         if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
 3             minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
 4         }
 5
 6         ensureExplicitCapacity(minCapacity);
 7     }
 8     private void ensureExplicitCapacity(int minCapacity) {
 9         modCount++;//
10         // overflow-conscious code
11         if (minCapacity - elementData.length > 0)
12             grow(minCapacity);
13     }
14  private void grow(int minCapacity) {
15         // overflow-conscious code
16         int oldCapacity = elementData.length;
17         int newCapacity = oldCapacity + (oldCapacity >> 1);
18         if (newCapacity - minCapacity < 0)
19             newCapacity = minCapacity;
20         if (newCapacity - MAX_ARRAY_SIZE > 0)
21             newCapacity = hugeCapacity(minCapacity);
22         // minCapacity is usually close to size, so this is a win:
23         elementData = Arrays.copyOf(elementData, newCapacity);
24     }

我们可以看到,在这个方法中,增加了一个判断,elementData ==DEFAULTCAPACITY_EMPTY_ELEMENTDATA,那么minCapacity=DEFAULT_CAPACITY,也就是等于10.这就区分出了前面所说的DEFAULTCAPACITY_EMPTY_ELEMENTDATA和EMPTY_ELEMENTDATA的区别。当elemetnDate=DEFAULT_CAPACITY时,第一次添加元素时,容量变为1,而当elementData =DEFAULTCAPACITY_EMPTY_ELEMENTDATA时,第一次添加元素时,容量变为10.
同时,我们也可以看出ArrayList在面对容量不足时,每次扩容都是在原容量的基础上,增加0.5倍。
而add(int index,E e)就比较好理解了,先检查index,然后判断是否需要扩容,需要就扩容,然后将原来的elemetnDate从index起始到最后复制到index+1的位置上,然后在原index位置添加元素。

ArrayList添加多个元素的方法一样有两个,分别为:

 1     public boolean addAll(Collection<? extends E> c) {
 2         Object[] a = c.toArray();
 3         int numNew = a.length;
 4         ensureCapacityInternal(size + numNew);  // Increments modCount
 5         System.arraycopy(a, 0, elementData, size, numNew);
 6         size += numNew;
 7         return numNew != 0;
 8     }
 9
10  public boolean addAll(int index, Collection<? extends E> c) {
11         rangeCheckForAdd(index);
12
13         Object[] a = c.toArray();
14         int numNew = a.length;
15         ensureCapacityInternal(size + numNew);  // Increments modCount
16
17         int numMoved = size - index;
18         if (numMoved > 0)
19             System.arraycopy(elementData, index, elementData, index + numNew,
20                              numMoved);
21
22         System.arraycopy(a, 0, elementData, index, numNew);
23         size += numNew;
24         return numNew != 0;
25     }

插入多个元素,与插入单个元素的逻辑是一样的,在这里就不再重复了。

ArrayList删除元素方法:

ArrayList删除元素的方法一共有五个,分别是

 1   public E remove(int index) {
 2         rangeCheck(index);
 3
 4         modCount++;
 5         E oldValue = elementData(index);
 6
 7         int numMoved = size - index - 1;
 8         if (numMoved > 0)
 9             System.arraycopy(elementData, index+1, elementData, index,
10                              numMoved);
11         elementData[--size] = null; // clear to let GC do its work
12
13         return oldValue;
14     }

remove(int index)的处理逻辑:先检查index是否大于elementDate的size,如果大于的话,则抛出异常;然后获取elementDate[index],留在方法结束后返回;然后复制素组,从index+1开始,复制size-index-1个元素,复制到elementDate,从index开始;最后设置elementDate[--size]=null;

 1     public boolean remove(Object o) {
 2         if (o == null) {
 3             for (int index = 0; index < size; index++)
 4                 if (elementData[index] == null) {
 5                     fastRemove(index);
 6                     return true;
 7                 }
 8         } else {
 9             for (int index = 0; index < size; index++)
10                 if (o.equals(elementData[index])) {
11                     fastRemove(index);
12                     return true;
13                 }
14         }
15         return false;
16     }

remove(Object o)的逻辑:先判断Object 是否为null,如果为null,则遍历ArrayList,删除所有的null值,如果有值被删除,则返回true;如果Object不为null,同样遍历ArrayList,删除ArrayList中相同的元素,如果有元素被删除,则返回true.

而fastRemove(int index)的逻辑与remove(int index),完全一致,只是少了对index的验证。

1  public boolean removeAll(Collection<?> c) {
2         Objects.requireNonNull(c);
3         return batchRemove(c, false);
4     }

 1  private boolean batchRemove(Collection<?> c, boolean complement) {
 2         final Object[] elementData = this.elementData;
 3         int r = 0, w = 0;
 4         boolean modified = false;
 5         try {
 6             for (; r < size; r++)
 7                 if (c.contains(elementData[r]) == complement)
 8                     elementData[w++] = elementData[r];
 9         } finally {
10             // Preserve behavioral compatibility with AbstractCollection,
11             // even if c.contains() throws.
12             if (r != size) {
13                 System.arraycopy(elementData, r,
14                                  elementData, w,
15                                  size - r);
16                 w += size - r;
17             }
18             if (w != size) {
19                 // clear to let GC do its work
20                 for (int i = w; i < size; i++)
21                     elementData[i] = null;
22                 modCount += size - w;
23                 size = w;
24                 modified = true;
25             }
26         }
27         return modified;
28     }

从上面的代码我们可以看出,remove(Collection<?> c)的逻辑:先判断c是否为null,如果为null,则抛出异常。然后遍历elementDate,如果c包含数组elementDate中的元素

,则将该元素添加一次替换原elementDate数组中,最后,将数组的其余位置设为null,如果新数组比原来数组中的元素少,则已经删除了元素,返回true.

除此之外,还有一个清空ArrayList的方法
1     public void clear() {
2         modCount++;
3
4         // clear to let GC do its work
5         for (int i = 0; i < size; i++)
6             elementData[i] = null;
7
8         size = 0;
9     }

clear()方法的逻辑:遍历,删除所有元素。

除此之外,还有一个retainAll(collenction<T> c)方法,该方法愿意是取得两个集合得交集,在这里也可以理解为删除集合中不与collection c 重复得元素。

1 return batchRemove(c, true);

可以看到,它得处理逻辑和removeAll是同样得逻辑,这里就不再重复了。

ArrayList修改元素的方法

在JDK1.8之前,修改元素只有一个方法,就是set(int index,Object c).

1  public E set(int index, E element) {
2         rangeCheck(index);
3
4         E oldValue = elementData(index);
5         elementData[index] = element;
6         return oldValue;
7     }

逻辑很简单,就是先检查index,然后新元素替换旧元素,并返回旧元素。

在JDK1.8中,添加了一个新方法,批量修改replaceAll(UnaryOperator<E> operator):

 1 public void replaceAll(UnaryOperator<E> operator) {
 2         Objects.requireNonNull(operator);
 3         final int expectedModCount = modCount;
 4         final int size = this.size;
 5         for (int i=0; modCount == expectedModCount && i < size; i++) {
 6             elementData[i] = operator.apply((E) elementData[i]);
 7         }
 8         if (modCount != expectedModCount) {
 9             throw new ConcurrentModificationException();
10         }
11         modCount++;
12     }

UnaryOperator<T> extends Function<T, T>,而Function<T,R>方法中有一个抽象方法,R apply<T,t>,方法的原意应该是将一个T转换成R.而这里使用,UnaryOperator,则只能将T转换成T。我们在使用ReplaceAll方法是,必须重写apply方法,作为转换规则。例如:

 1 public class ArrayListTest {
 2     public static void main(String[] args) {
 3         List<String> list = new ArrayList<String>();
 4         list.add("科比");
 5         list.add("詹姆斯");
 6         list.add("库里");
 7         list.replaceAll(new UnaryOperator<String>() {
 8             @Override
 9             public String apply(String t) {
10                 // TODO Auto-generated method stub
11                 return t+"牛逼";
12             }
13         });
14         System.out.println(list);
15     }
16 }

输出的结果为:

[科比牛逼, 詹姆斯牛逼, 库里牛逼]

ArrayList查找元素得方法:

  

1    public E get(int index) {
2         rangeCheck(index);
3
4         return elementData(index);
5     }

get(int index)方法,通过元素的下标来获取元素。其原理就是获取数组的当前下表的元素。

 1     public int indexOf(Object o) {
 2         if (o == null) {
 3             for (int i = 0; i < size; i++)
 4                 if (elementData[i]==null)
 5                     return i;
 6         } else {
 7             for (int i = 0; i < size; i++)
 8                 if (o.equals(elementData[i]))
 9                     return i;
10         }
11         return -1;
12     }

indextOf(Object o),查找ArrayList是否含有某元素,且返回该元素在集合中的第一个位置的下标。通过遍历元素,获取该集合所含有的第一个该元素的下标。如果不含有该元素,则返回-1.

 1     public int lastIndexOf(Object o) {
 2         if (o == null) {
 3             for (int i = size-1; i >= 0; i--)
 4                 if (elementData[i]==null)
 5                     return i;
 6         } else {
 7             for (int i = size-1; i >= 0; i--)
 8                 if (o.equals(elementData[i]))
 9                     return i;
10         }
11         return -1;
12     }

lastIndexOf(Object o),与indexOf方法想法,该方法查找该元素在集合中最后一个位置,并返回下标。其逻辑与indexOf基本一致,只不过是在遍历的时候选择从后往前遍历。

1 public boolean isEmpty() { 2 return size == 0; 3 }

isEmpth()方法用来查看集合是否为空集合。如果size=0,则为空集合,返回true。否则返回false。

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

 contains(Object o)查看集合中是否含有某元素。其调用indexOf(Object o),如果含有返回ture,否则返回false.

   public int size() {return size;}

 size()方法用来查看集合中含有多少个元素,返回元素个数。

ArrayList的一些其他常用方法:

 1    public Object clone() {
 2         try {
 3             ArrayList<?> v = (ArrayList<?>) super.clone();
 4             v.elementData = Arrays.copyOf(elementData, size);
 5             v.modCount = 0;
 6             return v;
 7         } catch (CloneNotSupportedException e) {
 8             // this shouldn't happen, since we are Cloneable
 9             throw new InternalError(e);
10         }
11     }

clone()方法,用来复制集合并返回一个新的集合。而查看copyOf源码,发现最底层是使用native方法进行的复制。我无法确定其到底是深复制还是浅复制。

private static native Object newArray(Class<?> componentType, int length) throws NegativeArraySizeException;

所以我写了一个简单的测试代码,代码如下:

 1 public class ArrayListTest{
 2     public static void main(String[] args) {
 3         ArrayList<User> list = new ArrayList<User>();
 4         list.add(new User("科比"));
 5         list.add(new User("詹姆斯"));
 6         list.add(new User("库里"));
 7         ArrayList list1= (ArrayList) list.clone();
 8         User user = list.get(1);
 9         user.name = "麦迪";
10         System.out.println(list1);
11     }
12 }
13
14 class User{
15      String name;
16     public User(String name){
17         this.name = name;
18     }
19     @Override
20     public String toString() {
21         return name;
22     }
23 }

打印结果为:

[科比, 麦迪, 库里]

  说明ArrayList的复制为潜复制,因为其数组中的元素,并没有进行值复制,而是直接复制了元素的引用。

在Java8中,ArrayList添加了一种新的遍历方法。foreach+lambda表达式遍历。代码如下:

1 public class ArrayListTest{
2     public static void main(String[] args) {
3         ArrayList<String> list = new ArrayList<String>();
4         list.add("科比");
5         list.add("詹姆斯");
6         list.add("库里");
7         list.forEach((s)->System.out.println(s));
8     }
9 }

因为不懂lambda表达式的实现原理,foreach的源码实在看不懂。等以后研究了lambda表达式的实现原理,在回来研究下foreach方法。

在Java8中,ArrayList同样新添加了一种排序方法。sort(Comparator<? super E> c).源码如下:

 1  @Override
 2     @SuppressWarnings("unchecked")
 3     public void sort(Comparator<? super E> c) {
 4         final int expectedModCount = modCount;
 5         Arrays.sort((E[]) elementData, 0, size, c);
 6         if (modCount != expectedModCount) {
 7             throw new ConcurrentModificationException();
 8         }
 9         modCount++;
10     }

发现,ArrayList的排序,其实就是调用了数组的排序。我们继续往下看,数组是如何排序的:

 1     public static <T> void sort(T[] a, int fromIndex, int toIndex,
 2                                 Comparator<? super T> c) {
 3         if (c == null) {
 4             sort(a, fromIndex, toIndex);
 5         } else {
 6             rangeCheck(a.length, fromIndex, toIndex);
 7             if (LegacyMergeSort.userRequested)
 8                 legacyMergeSort(a, fromIndex, toIndex, c);
 9             else
10                 TimSort.sort(a, fromIndex, toIndex, c, null, 0, 0);
11         }
12     }

1     public static void sort(Object[] a, int fromIndex, int toIndex) {
2         rangeCheck(a.length, fromIndex, toIndex);
3         if (LegacyMergeSort.userRequested)
4             legacyMergeSort(a, fromIndex, toIndex);
5         else
6             ComparableTimSort.sort(a, fromIndex, toIndex, null, 0, 0);
7     }

1  private static void legacyMergeSort(Object[] a,
2                                         int fromIndex, int toIndex) {
3         Object[] aux = copyOfRange(a, fromIndex, toIndex);
4         mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
5     }

 1 @SuppressWarnings({"unchecked", "rawtypes"})
 2     private static void mergeSort(Object[] src,
 3                                   Object[] dest,
 4                                   int low,
 5                                   int high,
 6                                   int off) {
 7         int length = high - low;
 8
 9         // Insertion sort on smallest arrays
10         if (length < INSERTIONSORT_THRESHOLD) {
11             for (int i=low; i<high; i++)
12                 for (int j=i; j>low &&
13                          ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
14                     swap(dest, j, j-1);
15             return;
16         }
17
18         // Recursively sort halves of dest into src
19         int destLow  = low;
20         int destHigh = high;
21         low  += off;
22         high += off;
23         int mid = (low + high) >>> 1;
24         mergeSort(dest, src, low, mid, -off);
25         mergeSort(dest, src, mid, high, -off);
26
27         // If list is already sorted, just copy from src to dest.  This is an
28         // optimization that results in faster sorts for nearly ordered lists.
29         if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
30             System.arraycopy(src, low, dest, destLow, length);
31             return;
32         }
33
34         // Merge sorted halves (now in src) into dest
35         for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
36             if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0)
37                 dest[i] = src[p++];
38             else
39                 dest[i] = src[q++];
40         }
41     }

1    /** To be removed in a future release. */
2     private static <T> void legacyMergeSort(T[] a, int fromIndex, int toIndex,
3                                             Comparator<? super T> c) {
4         T[] aux = copyOfRange(a, fromIndex, toIndex);
5         if (c==null)
6             mergeSort(aux, a, fromIndex, toIndex, -fromIndex);
7         else
8             mergeSort(aux, a, fromIndex, toIndex, -fromIndex, c);
9     }

 1    @SuppressWarnings({"rawtypes", "unchecked"})
 2     private static void mergeSort(Object[] src,
 3                                   Object[] dest,
 4                                   int low, int high, int off,
 5                                   Comparator c) {
 6         int length = high - low;
 7
 8         // Insertion sort on smallest arrays
 9         if (length < INSERTIONSORT_THRESHOLD) {
10             for (int i=low; i<high; i++)
11                 for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
12                     swap(dest, j, j-1);
13             return;
14         }
15
16         // Recursively sort halves of dest into src
17         int destLow  = low;
18         int destHigh = high;
19         low  += off;
20         high += off;
21         int mid = (low + high) >>> 1;
22         mergeSort(dest, src, low, mid, -off, c);
23         mergeSort(dest, src, mid, high, -off, c);
24
25         // If list is already sorted, just copy from src to dest.  This is an
26         // optimization that results in faster sorts for nearly ordered lists.
27         if (c.compare(src[mid-1], src[mid]) <= 0) {
28            System.arraycopy(src, low, dest, destLow, length);
29            return;
30         }
31
32         // Merge sorted halves (now in src) into dest
33         for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
34             if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0)
35                 dest[i] = src[p++];
36             else
37                 dest[i] = src[q++];
38         }
39     }

可以看出,当比较器为空时,调用了mergeSort(Object[] src,Object[] dest,int low, int high, int off方法,不为空时,调用了mergeSort(Object[] src,Object[] dest,int low, int high, int off,Comparator c方法,两个方法基本一模一样,唯一的区别就是在有默认比较器的时候,两个元素的比较实用默认比较器的比较方法来比较。

仔细看两个方法,可以看出,ArrayList.sort方法 时间上是使用了一种优化过后的递归排序,在数组长度小于7的时候使用直接插入排序。数组长度大于7的时候,使用归并排序,直至子数组的长度小于7.

归并排序详见我的另一篇随笔经典排序算法--归并排序。

写在最后:

  此篇随笔仅用来记录我的学习内容,如有错误,欢迎指正。谢谢!!!

转载于:https://www.cnblogs.com/xsyfl/p/6842946.html

ArrayList源码解析相关推荐

  1. 增加数组下标_数组以及ArrayList源码解析

    点击上方"码之初"关注,···选择"设为星标" 与精品技术文章不期而遇 前言 前一篇我们对数据结构有了个整体的概念上的了解,没看过的小伙伴们可以看我的上篇文章: ...

  2. 面试官系统精讲Java源码及大厂真题 - 05 ArrayList 源码解析和设计思路

    05 ArrayList 源码解析和设计思路 耐心和恒心总会得到报酬的. --爱因斯坦 引导语 ArrayList 我们几乎每天都会使用到,但真正面试的时候,发现还是有不少人对源码细节说不清楚,给面试 ...

  3. 顺序线性表 ---- ArrayList 源码解析及实现原理分析

    原创播客,如需转载请注明出处.原文地址:http://www.cnblogs.com/crawl/p/7738888.html ------------------------------------ ...

  4. ArrayList源码解析与相关知识点

    ArrayList源码解析于相关知识点(超级详细) 文章目录 ArrayList源码解析于相关知识点(超级详细) ArrayList的继承关系 Serializable标记接口 Cloneable标记 ...

  5. 面试必备:ArrayList源码解析(JDK8)

    概述 很久没有写博客了,准确的说17年以来写博客的频率降低到一个不忍直视的水平.这个真不怪我,给大家解释一下.  一是自从做了leader,整天各种事,开会,过需求,无限循环.心很累,时间也被无线压榨 ...

  6. Java集合-ArrayList源码解析-JDK1.8

    ◆ ArrayList简介 ◆ ArrayList 是一个数组队列,相当于 动态数组.与Java中的数组相比,它的容量能动态增长.它继承于AbstractList,实现了List, RandomAcc ...

  7. 安卓开发者必看:Android的数据结构与算法——ArrayList源码解析

    作者:JerryloveEmily 原文链接:https://www.jianshu.com/p/159426e2aaf6 文章有点长,比较啰嗦,请耐心看完! 一.概述 首先得明白ArrayList在 ...

  8. Android的数据结构与算法----ArrayList源码解析

    转载请标明出处: http://blog.csdn.net/abren32/article/details/56669369 本文出自JerryloveEmily的博客 文章有点长,比较啰嗦,请耐心看 ...

  9. ArrayList源码解析之subList

    ArrayList的 subList ( int fromIndex, int toIndex ) 方法执行结果是获取ArrayList的一部分,返回的是ArrayList的部分视图.<阿里巴巴 ...

  10. 给jdk写注释系列之jdk1.6容器(1):ArrayList源码解析

    前言: 工作中经常听到别人讲"容器",各种各样的容器,话说到底什么是容器,通俗的讲"容器就是用来装东西的器皿,比如:水桶就是用来盛水的,水桶就是一个容器." o ...

最新文章

  1. 在MySQL查询山东省男生信息_mysql查询语句
  2. 巴巴腾机器人怎么开机_【巴巴腾智能机器人使用】_摘要频道_什么值得买
  3. 【推荐系统】AAAI2022推荐系统论文集锦
  4. 为别人做嫁衣——代理模式
  5. Bootstrap 表单的扩展控件
  6. dedecms php5.4 无法退出后台,DedeCMS 织梦在 Windows 的 PHP5.4 环境下登录后台空白的解决办法...
  7. Android 性能优化:使用 Lint 优化代码、去除多余资源,减少APP的size
  8. 计算机网络自顶向下方法第6章-链路层和局域网.1
  9. 啃完这本阿里手册,应届七面进阿里
  10. java将域名解析为IP地址,获取网卡的配置信息
  11. Java数据结构-Set
  12. J2EE基础教程(4):struts框架(视频笔记)
  13. 网易视频云CEO余利华:云服务的核心仍是用户体验
  14. [原创]从程序员角度分析安徽电信HTTP劫持的无耻行径 – 之深度分析
  15. 指尖江湖李忘生鸿蒙初开,剑网3指尖江湖李忘生技能搭配攻略
  16. 科思创筹建上海新工厂;宝投集团与通快签约大湾区激光应用研发中心项目 | 能动...
  17. 高智商翻木块java_高智商游戏翻木块
  18. Git仓库迁移超简单步骤
  19. UG CAD高级塑胶模具结构讲解视频教程
  20. Java 微信上传临时素材

热门文章

  1. 在M1 mac 使用Ps 2021上导出 PNG 格式发生未知错误如何解决?
  2. 苹果 macOS Monterey 桌面抽象风格不好看,如何换成自己喜欢的照片?
  3. markdown编辑软件Ulysses 24.5 for Mac
  4. 如何在 macOS Monterey 正式发布之前备份您的 Automator 作品?
  5. 在Mac上如何管理添加,删除和延迟启动项
  6. iClock时间菜单功能设置
  7. 小白如何购买阿里云服务器(2019最详细教程)
  8. 微软打造Unity开发工具包 为视力低落的用户增加辅助功能
  9. action属性注入为null
  10. Oracle 开放源代码项目