1 public Object[] toArray() { 2 // Estimate size of array; be prepared to see more or fewer elements 3 Object[] r = new Object[size()]; 4 Iterator<E> it = iterator(); 5 for (int i = 0; i < r.length; i++) { 6 if (! it.hasNext()) // fewer elements than expected 7 return Arrays.copyOf(r, i); 8 r[i] = it.next(); 9 } 10 return it.hasNext() ? finishToArray(r, it) : r;
- 先根据size()的大小生成一个数组,然后根据迭代器的hasNext来判断,当前迭代器后面还有没有值,并用i记录当前的已经存入的元素数量。
- 如果迭代器实际迭代的数量的大小比size小,则使用Arrays.copyOf来截断当前的数组,然后直接返回。
- 需要说明的是Arrays的静态方法是java针对数组来实现的一系列方法。其中copyOf将传入的数组复制到一个新的数组中,新的数组的大小由第二个参数来指定。
- 如果迭代器实际迭代的数量的大小比size大,则调用finishToArray来完成之后迭代器的实现。
1 @SuppressWarnings("unchecked") 2 private static <T> T[] finishToArray(T[] r, Iterator<?> it) { 3 int i = r.length; 4 while (it.hasNext()) { 5 int cap = r.length; 6 if (i == cap) { 7 int newCap = cap + (cap >> 1) + 1; 8 // overflow-conscious code 9 if (newCap - MAX_ARRAY_SIZE > 0) 10 newCap = hugeCapacity(cap + 1); 11 r = Arrays.copyOf(r, newCap); 12 } 13 r[i++] = (T)it.next(); 14 } 15 // trim if overallocated 16 return (i == r.length) ? r : Arrays.copyOf(r, i); 17 }
- i表示当前的迭代的元素的数量,总的来说i每次进入循环体就增加一个.而另一个cap表示当前的数组的大小。
- 第一次进入i==cap,说明需要增大cap。这里增加的cap的一半并加1的大小,然后判断下新的数组的大小是否超过VM的最大界限,如果没有就将继续循环体。
- 每次进入循环体,先用cap确认下当前数组的长度。如果i还没有增长到cap相同的程度则只要将迭代器的下一个元素放入数组并将i加一就行
- 在返回的时候使用根据已经迭代的元素i来复制当前数组到一个新的数组中。
1 private static int hugeCapacity(int minCapacity) { 2 if (minCapacity < 0) // overflow 3 throw new OutOfMemoryError 4 ("Required array size too large"); 5 return (minCapacity > MAX_ARRAY_SIZE) ? 6 Integer.MAX_VALUE : 7 MAX_ARRAY_SIZE; 8 }
- 如果当前的cap最大值不可在继续增大,即cap+1为负值则抛出一个超出内存大小的异常。Integer.MAX_VALUE+1 <0
- 如果当前的值可以分配,则分配一个MAX_ARRAY_SIZE和MAX_VALUE 中的满足条件的值。
1 @SuppressWarnings("unchecked") 2 public <T> T[] toArray(T[] a) { 3 // Estimate size of array; be prepared to see more or fewer elements 4 int size = size(); 5 T[] r = a.length >= size ? a : 6 (T[])java.lang.reflect.Array 7 .newInstance(a.getClass().getComponentType(), size); 8 Iterator<E> it = iterator(); 9 10 for (int i = 0; i < r.length; i++) { 11 if (! it.hasNext()) { // fewer elements than expected 12 if (a == r) { 13 r[i] = null; // null-terminate 14 } else if (a.length < i) { 15 return Arrays.copyOf(r, i); 16 } else { 17 System.arraycopy(r, 0, a, 0, i); 18 if (a.length > i) { 19 a[i] = null; 20 } 21 } 22 return a; 23 } 24 r[i] = (T)it.next(); 25 } 26 // more elements than expected 27 return it.hasNext() ? finishToArray(r, it) : r; 28 }
- i表示当前的迭代的元素的数量,传入的参数a的大小,以及size返回的大小
- 如果是比预期少的元素,需要分情况讨论,r引用的就是a,则让a数组位置i为null。
- r引用不是a。说明a.length<size,新的数组说明是根据size新建的数组。如果a的长度小于i,说明这些值没办法放入到a中,则需要返回自建建立的数组而没办法返回原先的参数a,所有只要对r进行截断后返回就可以了
- 如果是a的长度>i,这说明了传入的参数a是可以放入足够的参数的,这里将r中的所有元素复制到a中,并进行截断然后返回,则让a数组位置i为null。
- 下同toArray().