1简介

  1. public class ArrayList<E> extends AbstractList<E>
  2. implements List<E>, RandomAccess, Cloneable, java.io.Serializable

ArrayList使用一个可变数组实现List接口,实现了List接口的所有可选操作。ArrayList除了是非线程安全的之外,其他的与Vector类似。

2成员属性

  1. //序列化版本号
  2. private static final long serialVersionUID = 8683452581122892189L;
  3.  
  4. //默认容量
  5. private static final int DEFAULT_CAPACITY = 10;
  6.  
  7. //默认数组,没有元素,空数组
  8. private static final Object[] EMPTY_ELEMENTDATA = {};
  9.  
  10. //默认容量数组
  11. private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
  12.  
  13. //存放元素的数组
  14. transient Object[] elementData;
  15.  
  16. //当前ArrayList里面元素存放数量
  17. private int size;

3构造函数

  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: "+ initialCapacity);
  8. }
  9. }
  10.  
  11. public ArrayList() {
  12. this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
  13. }
  14.  
  15. public ArrayList(Collection<? extends E> c) {
  16. elementData = c.toArray();
  17. if ((size = elementData.length) != 0) {
  18. // c.toArray might (incorrectly) not return Object[] (see 6260652)
  19. if (elementData.getClass() != Object[].class)
  20. elementData = Arrays.copyOf(elementData, size, Object[].class);
  21. } else {
  22. // replace with empty array.
  23. this.elementData = EMPTY_ELEMENTDATA;
  24. }
  25. }

上面几个构造函数没什么好讲的,但有一个疑问,正常来说DEFAULTCAPACITY_EMPTY_ELEMENTDATA容量应该为10,可是我们在属性的里声明的时候却是为空的,为什么会这样?不急,接下来的扩容代码给出了很好的解释。与Vector一样,ArrayList可以调用trimToSize将多余的空间释放,也可以扩充容量。

4可收缩容量

(1)trimToSize方法

  1. public void trimToSize() {
  2. modCount++;
  3. if (size < elementData.length) {
  4. elementData = (size == 0)
  5. ? EMPTY_ELEMENTDATA
  6. : Arrays.copyOf(elementData, size);
  7. }
  8. }

size属性是集合里现有元素的个数,elementData.length是数组的实际长度。我们可以trimToSize将数组标号为[size,elementData.length-1]的空间释放。

(2)扩容

  1. public void ensureCapacity(int minCapacity) {
  2. int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
  3. // any size if not default element table
  4. ? 0
  5. // larger than default for default empty table. It's already
  6. // supposed to be at default size.
  7. : DEFAULT_CAPACITY;
  8.  
  9. if (minCapacity > minExpand) {
  10. ensureExplicitCapacity(minCapacity);
  11. }
  12. }
  13.  
  14. private static int calculateCapacity(Object[] elementData, int minCapacity) {
  15. if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
  16. return Math.max(DEFAULT_CAPACITY, minCapacity);
  17. }
  18. return minCapacity;
  19. }
  20.  
  21. private void ensureCapacityInternal(int minCapacity) {
  22. ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
  23. }
  24.  
  25. private void ensureExplicitCapacity(int minCapacity) {
  26. modCount++;
  27.  
  28. // overflow-conscious code
  29. if (minCapacity - elementData.length > 0)
  30. grow(minCapacity);
  31. }
  32.  
  33. private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
  34.  
  35. private void grow(int minCapacity) {
  36. // overflow-conscious code
  37. int oldCapacity = elementData.length;
  38. int newCapacity = oldCapacity + (oldCapacity >> 1);
  39. if (newCapacity - minCapacity < 0)
  40. newCapacity = minCapacity;
  41. if (newCapacity - MAX_ARRAY_SIZE > 0)
  42. newCapacity = hugeCapacity(minCapacity);
  43. // minCapacity is usually close to size, so this is a win:
  44. elementData = Arrays.copyOf(elementData, newCapacity);
  45. }
  46.  
  47. private static int hugeCapacity(int minCapacity) {
  48. if (minCapacity < 0) // overflow
  49. throw new OutOfMemoryError();
  50. return (minCapacity > MAX_ARRAY_SIZE) ?
  51. Integer.MAX_VALUE :
  52. MAX_ARRAY_SIZE;
  53. }

我们先解释一下DEFAULTCAPACITY_EMPTY_ELEMENTDATA容量问题:

当调用add方法添加元素时,首先会执行ensureCapacityInternal(size + 1),进入该方法后只有一条ensureExplicitCapacity(calculateCapacity(elementData, minCapacity)),当elementData是DEFAULTCAPACITY_EMPTY_ELEMENTDATA时,calculateCapacity方法会返回DEFAULT_CAPACITY和size + 1的较大值。size默认从0开始的,所以第一次调用add方法时且当elementData是DEFAULTCAPACITY_EMPTY_ELEMENTDATA时,就会对进行扩容操作,而扩容的容量正好是DEFAULT_CAPACITY(10)。

然后我们分析手动调用ensureCapacity(minCapacity)进行扩容的过程:

进入该方法后,第一步是求minExpand,这里会判读实际数组是否等于DEFAULTCAPACITY_EMPTY_ELEMENTDATA,若是的话minExpand赋值为DEFAULT_CAPACITY(10),否则为0。然后确保参数minCapacity大于minExpand,才进行后续的扩容操作,调用ensureExplicitCapacity(minCapacity)。

ensureExplicitCapacity方法确保minCapacity大于当前容量elementData.length才进行扩容操作,调用 grow(minCapacity)。

因为扩容原理是复制数组,这是个是个很费计算机资源的操作,应该尽量减少扩容次数,所以每次扩容都会保证最小扩容(旧容量*1.5),grow方法的主要功能就是这个。

5查找

  1. public boolean contains(Object o) {
  2. return indexOf(o) >= 0;
  3. }
  4.  
  5. //查找第一个索引
  6. public int indexOf(Object o) {
  7. if (o == null) {
  8. for (int i = 0; i < size; i++)
  9. if (elementData[i]==null)
  10. return i;
  11. } else {
  12. for (int i = 0; i < size; i++)
  13. if (o.equals(elementData[i]))
  14. return i;
  15. }
  16. return -1;
  17. }
  18.  
  19. //查找最后一个索引
  20. public int lastIndexOf(Object o) {
  21. if (o == null) {
  22. for (int i = size-1; i >= 0; i--)
  23. if (elementData[i]==null)
  24. return i;
  25. } else {
  26. for (int i = size-1; i >= 0; i--)
  27. if (o.equals(elementData[i]))
  28. return i;
  29. }
  30. return -1;
  31. }
  32.  
  33. //获取索引位置元素
  34. public E get(int index) {
  35. rangeCheck(index);
  36.  
  37. return elementData(index);
  38. }
  39. //set放着一起看吧
  40. public E set(int index, E element) {
  41. rangeCheck(index);
  42.  
  43. E oldValue = elementData(index);
  44. elementData[index] = element;
  45. return oldValue;
  46. }
  47.  
  48. private void rangeCheck(int index) {
  49. if (index >= size)
  50. throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
  51. }

查找的时候注意判断null,因为null.equals()是会报空指针异常的。indexOf是从前往后遍历数组,lastIndexOf则是从后往前遍历。

6集合基本操作

(1)添加元素

  1. //在末尾添加一个元素
  2. public boolean add(E e) {
  3. ensureCapacityInternal(size + 1); // 检查是否需要扩容
  4. elementData[size++] = e;
  5. return true;
  6. }
  7.  
  8. //在指定位置添加一个元素
  9. public void add(int index, E element) {
  10. rangeCheckForAdd(index);
  11.  
  12. ensureCapacityInternal(size + 1); // Increments modCount!!
  13. System.arraycopy(elementData, index, elementData, index + 1,size - index); // index后的所有元素均后移一位
  14. elementData[index] = element;
  15. size++;
  16. }
  17.  
  18. //添加一堆元素
  19. public boolean addAll(Collection<? extends E> c) {
  20. Object[] a = c.toArray();
  21. int numNew = a.length;
  22. ensureCapacityInternal(size + numNew); // Increments modCount
  23. System.arraycopy(a, 0, elementData, size, numNew);
  24. size += numNew;
  25. return numNew != 0;
  26. }
  27. //从指定位置开始添加一堆元素
  28. public boolean addAll(int index, Collection<? extends E> c) {
  29. rangeCheckForAdd(index);
  30.  
  31. Object[] a = c.toArray();
  32. int numNew = a.length;
  33. ensureCapacityInternal(size + numNew); // Increments modCount
  34.  
  35. int numMoved = size - index;
  36. if (numMoved > 0)
  37. System.arraycopy(elementData, index, elementData, index + numNew,
  38. numMoved);
  39.  
  40. System.arraycopy(a, 0, elementData, index, numNew);
  41. size += numNew;
  42. return numNew != 0;
  43. }
  44.  
  45. private void rangeCheckForAdd(int index) {
  46. if (index > size || index < 0)
  47. throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
  48. }

(2)删除元素

  1. //删除指定位置的元素
  2. public E remove(int index) {
  3. rangeCheck(index);
  4.  
  5. modCount++;
  6. E oldValue = elementData(index);
  7.  
  8. int numMoved = size - index - 1;
  9. if (numMoved > 0)
  10. System.arraycopy(elementData, index+1, elementData, index, numMoved);
  11. elementData[--size] = null; // clear to let GC do its work
  12.  
  13. return oldValue;
  14. }
  15.  
  16. //删除匹配的元素
  17. public boolean remove(Object o) {
  18. if (o == null) {
  19. for (int index = 0; index < size; index++)
  20. if (elementData[index] == null) {
  21. fastRemove(index);
  22. return true;
  23. }
  24. } else {
  25. for (int index = 0; index < size; index++)
  26. if (o.equals(elementData[index])) {
  27. fastRemove(index);
  28. return true;
  29. }
  30. }
  31. return false;
  32. }
  33.  
  34. private void fastRemove(int index) {
  35. modCount++;
  36. int numMoved = size - index - 1;
  37. if (numMoved > 0)
  38. System.arraycopy(elementData, index+1, elementData, index,
  39. numMoved);
  40. elementData[--size] = null; // clear to let GC do its work
  41. }
  42.  
  43. //删除索引为[fromIndex,toIndex]范围内的所以元素
  44. protected void removeRange(int fromIndex, int toIndex) {
  45. modCount++;
  46. int numMoved = size - toIndex;
  47. System.arraycopy(elementData, toIndex, elementData, fromIndex,
  48. numMoved);
  49.  
  50. // clear to let GC do its work
  51. int newSize = size - (toIndex-fromIndex);
  52. for (int i = newSize; i < size; i++) {
  53. elementData[i] = null;
  54. }
  55. size = newSize;
  56. }
  57.  
  58. //删除一堆元素
  59. public boolean removeAll(Collection<?> c) {
  60. Objects.requireNonNull(c); //检查集合c不能为空,否则报空指针异常
  61. return batchRemove(c, false);
  62. }
  63.  
  64. private boolean batchRemove(Collection<?> c, boolean complement) {
  65. final Object[] elementData = this.elementData;
  66. int r = 0, w = 0;
  67. boolean modified = false;
  68. try {
  69. for (; r < size; r++)
  70. if (c.contains(elementData[r]) == complement)
  71. elementData[w++] = elementData[r];
  72. } finally {
  73. // Preserve behavioral compatibility with AbstractCollection,
  74. // even if c.contains() throws.
  75. if (r != size) {
  76. System.arraycopy(elementData, r,
  77. elementData, w,
  78. size - r);
  79. w += size - r;
  80. }
  81. if (w != size) {
  82. // clear to let GC do its work
  83. for (int i = w; i < size; i++)
  84. elementData[i] = null;
  85. modCount += size - w;
  86. size = w;
  87. modified = true;
  88. }
  89. }
  90. return modified;
  91. }
  92.  
  93. //清空(删除所有元素)
  94. public void clear() {
  95. modCount++;
  96.  
  97. // clear to let GC do its work
  98. for (int i = 0; i < size; i++)
  99. elementData[i] = null;
  100.  
  101. size = 0;
  102. }

remove和fastRemove的区别是后者没有范围检查,只有确定不会越界的情况下才会调用fastRemove来提升效率。

值得注意的是与Vector不同,这里删除一堆元素不是通过迭代器实现的,而是通过batchRemove方法,该批量删除方法会遍历数据数组。当complement参数为false时,把不属于参数集合里的元素替换到原数组里面。为true时,把原集合中属于参数集合里的元素替换到原数组里面。

7序列化方法

由于ArrayList实现了Serializable接口,我们知道它是可序列化的,而且该类自己实现了序列化writeObject和反序列化readObject方法,当ObjectOutputStream调用writeObject进行序列化时,会调用该类自己的writeObject。同理,ObjectInputStream也会调用该类自己的readObject方法实现反序列化。

  1. private void writeObject(java.io.ObjectOutputStream s)
  2. throws java.io.IOException{
  3. // Write out element count, and any hidden stuff
  4. int expectedModCount = modCount;
  5. s.defaultWriteObject();
  6.  
  7. // Write out size as capacity for behavioural compatibility with clone()
  8. s.writeInt(size);
  9.  
  10. // Write out all elements in the proper order.
  11. for (int i=0; i<size; i++) {
  12. s.writeObject(elementData[i]);
  13. }
  14.  
  15. if (modCount != expectedModCount) {
  16. throw new ConcurrentModificationException();
  17. }
  18. }
  19.  
  20. private void readObject(java.io.ObjectInputStream s)
  21. throws java.io.IOException, ClassNotFoundException {
  22. elementData = EMPTY_ELEMENTDATA;
  23.  
  24. // Read in size, and any hidden stuff
  25. s.defaultReadObject();
  26.  
  27. // Read in capacity
  28. s.readInt(); // ignored
  29.  
  30. if (size > 0) {
  31. // be like clone(), allocate array based upon size not capacity
  32. int capacity = calculateCapacity(elementData, size);
  33. SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
  34. ensureCapacityInternal(size);
  35.  
  36. Object[] a = elementData;
  37. // Read in all elements in the proper order.
  38. for (int i=0; i<size; i++) {
  39. a[i] = s.readObject();
  40. }
  41. }
  42. }

writeObject方法第一步是获得当前modCount,这样做的目的是确保在方法执行过程中,ArrayList对象没有其他线程修改。然后是调用ObjectOutputStream 的defaultWriteObject

方法将ArrayList对象的非static 和非transient的属性写出到当前流。下一步是将集合中当前数据量size写出,最后遍历数组,将每个位置的对象写出。

readObject方法的工作稍复杂,在进行反序列化之前需要2个工作,第一个是数据检查,确保读过来的是Object数组。第二个是开辟合理的空间存储取回来的数据。

8迭代器实现

ArrayList的祖先Collection继承了Iterable接口,ArrayList是通过内部类实现迭代器的。

  1. public Iterator<E> iterator() {
  2. return new Itr();
  3. }
  4.  
  5. /**
  6. * An optimized version of AbstractList.Itr
  7. */
  8. private class Itr implements Iterator<E> {
  9. int cursor; // index of next element to return
  10. int lastRet = -1; // index of last element returned; -1 if no such
  11. int expectedModCount = modCount;
  12.  
  13. Itr() {}
  14.  
  15. public boolean hasNext() {
  16. return cursor != size;
  17. }
  18.  
  19. @SuppressWarnings("unchecked")
  20. public E next() {
  21. checkForComodification();
  22. int i = cursor;
  23. if (i >= size)
  24. throw new NoSuchElementException();
  25. Object[] elementData = ArrayList.this.elementData;
  26. if (i >= elementData.length)
  27. throw new ConcurrentModificationException();
  28. cursor = i + 1;
  29. return (E) elementData[lastRet = i];
  30. }
  31.  
  32. public void remove() {
  33. if (lastRet < 0)
  34. throw new IllegalStateException();
  35. checkForComodification();
  36.  
  37. try {
  38. ArrayList.this.remove(lastRet);
  39. cursor = lastRet;
  40. lastRet = -1;
  41. expectedModCount = modCount;
  42. } catch (IndexOutOfBoundsException ex) {
  43. throw new ConcurrentModificationException();
  44. }
  45. }
  46.  
  47. @Override
  48. @SuppressWarnings("unchecked")
  49. public void forEachRemaining(Consumer<? super E> consumer) {
  50. Objects.requireNonNull(consumer);
  51. final int size = ArrayList.this.size;
  52. int i = cursor;
  53. if (i >= size) {
  54. return;
  55. }
  56. final Object[] elementData = ArrayList.this.elementData;
  57. if (i >= elementData.length) {
  58. throw new ConcurrentModificationException();
  59. }
  60. while (i != size && modCount == expectedModCount) {
  61. consumer.accept((E) elementData[i++]);
  62. }
  63. // update once at end of iteration to reduce heap write traffic
  64. cursor = i;
  65. lastRet = i - 1;
  66. checkForComodification();
  67. }
  68.  
  69. final void checkForComodification() {
  70. if (modCount != expectedModCount)
  71. throw new ConcurrentModificationException();
  72. }
  73. }

关于ArrayList迭代的实现请参考我的另一篇文章:Java迭代器

对于ArrayList不仅有其Iterator实现,还有ListIterator的实现。ListIterator不仅可以向后遍历,而且可以向前遍历。

  1. private class ListItr extends Itr implements ListIterator<E> {
  2. ListItr(int index) {
  3. super();
  4. cursor = index;
  5. }
  6.  
  7. public boolean hasPrevious() {
  8. return cursor != 0;
  9. }
  10.  
  11. public int nextIndex() {
  12. return cursor;
  13. }
  14.  
  15. public int previousIndex() {
  16. return cursor - 1;
  17. }
  18.  
  19. @SuppressWarnings("unchecked")
  20. public E previous() {
  21. checkForComodification();
  22. int i = cursor - 1;
  23. if (i < 0)
  24. throw new NoSuchElementException();
  25. Object[] elementData = ArrayList.this.elementData;
  26. if (i >= elementData.length)
  27. throw new ConcurrentModificationException();
  28. cursor = i;
  29. return (E) elementData[lastRet = i];
  30. }
  31.  
  32. public void set(E e) {
  33. if (lastRet < 0)
  34. throw new IllegalStateException();
  35. checkForComodification();
  36.  
  37. try {
  38. ArrayList.this.set(lastRet, e);
  39. } catch (IndexOutOfBoundsException ex) {
  40. throw new ConcurrentModificationException();
  41. }
  42. }
  43.  
  44. public void add(E e) {
  45. checkForComodification();
  46.  
  47. try {
  48. int i = cursor;
  49. ArrayList.this.add(i, e);
  50. cursor = i + 1;
  51. lastRet = -1;
  52. expectedModCount = modCount;
  53. } catch (IndexOutOfBoundsException ex) {
  54. throw new ConcurrentModificationException();
  55. }
  56. }
  57. }

ListIterator向后迭代的过程继承自Iterator,这里没什么好说的。这里主要分析previous()、set(E e)、add(E e)三个方法。

(1)previous()方法

该方法定义前向迭代的过程,首先将当前游标cursor向前移动一位,再把游标移动后指向的位置赋值给lastRet,最后返回lastRet指向的值。

(2)set(E e)方法

该方法将lastRet指向位置的值改为指定值(参数)。

(3)add(E e)方法

该方法在cursor位置插入指定值,然后将游标位置后移1位,并将lastRet置为-1。

9其他

(1)排序

ArryList内部提供了排序方法sort,sort方法就是接受了一个Comparator比较器对象,然后将List集合转换成数组,然后再调用数组工具类Arrays的sort()方法进行排序,最后把排好序的数组遍历并赋值到原来的List集合上。

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

(2)removeIf方法

该方法的调用依赖于函数编程,需要传入一个函数作为参数,符合该函数判定为true的元素进行删除操作。

  1. public boolean removeIf(Predicate<? super E> filter) {
  2. Objects.requireNonNull(filter);
  3. // figure out which elements are to be removed
  4. // any exception thrown from the filter predicate at this stage
  5. // will leave the collection unmodified
  6. int removeCount = 0;
  7. final BitSet removeSet = new BitSet(size);
  8. final int expectedModCount = modCount;
  9. final int size = this.size;
  10. for (int i=0; modCount == expectedModCount && i < size; i++) {
  11. @SuppressWarnings("unchecked")
  12. final E element = (E) elementData[i];
  13. if (filter.test(element)) {
  14. removeSet.set(i);
  15. removeCount++;
  16. }
  17. }
  18. if (modCount != expectedModCount) {
  19. throw new ConcurrentModificationException();
  20. }
  21.  
  22. // shift surviving elements left over the spaces left by removed elements
  23. final boolean anyToRemove = removeCount > 0;
  24. if (anyToRemove) {
  25. final int newSize = size - removeCount;
  26. for (int i=0, j=0; (i < size) && (j < newSize); i++, j++) {
  27. i = removeSet.nextClearBit(i);
  28. elementData[j] = elementData[i];
  29. }
  30. for (int k=newSize; k < size; k++) {
  31. elementData[k] = null; // Let gc do its work
  32. }
  33. this.size = newSize;
  34. if (modCount != expectedModCount) {
  35. throw new ConcurrentModificationException();
  36. }
  37. modCount++;
  38. }
  39.  
  40. return anyToRemove;
  41. }

line13的代码filter.test(element)判断符合条件的元素,这里通过位运算记录需要操作的位置,然后进行数组复制。(关于如何通过位运算记录删除位请详细阅读BitSet类源码)

(3)forEach方法

该方法和前面迭代器一节中的forEachRemaining类似,也是Java8函数编程新特性。forEach的作用是为集合中的每个元素执行一些操作(操作函数作为参数传入)

  1. public void forEach(Consumer<? super E> action) {
  2. Objects.requireNonNull(action);
  3. final int expectedModCount = modCount;
  4. @SuppressWarnings("unchecked")
  5. final E[] elementData = (E[]) this.elementData;
  6. final int size = this.size;
  7. for (int i=0; modCount == expectedModCount && i < size; i++) {
  8. action.accept(elementData[i]);
  9. }
  10. if (modCount != expectedModCount) {
  11. throw new ConcurrentModificationException();
  12. }
  13. }

(4)subList

  1. List<E> subList(int fromIndex, int toIndex);
  • 该方法返回的是父list的一个视图,从fromIndex(包含),到toIndex(不包含)。fromIndex=toIndex 表示子list为空
  • 父子list做的非结构性修改(non-structural changes)都会影响到彼此:所谓的“非结构性修改”,是指不涉及到list的大小改变的修改。相反,结构性修改,指改变了list大小的修改。
  • 对于结构性修改,子list的所有操作都会反映到父list上。但父list的修改将会导致返回的子list失效。
  • 如何删除list中的某段数据:list.subList(from, to).clear();

代码这里我就不贴了。

Java源码阅读ArrayList的更多相关文章

  1. Java源码阅读的真实体会(一种学习思路)

    Java源码阅读的真实体会(一种学习思路) 刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈 ...

  2. Java源码阅读的真实体会(一种学习思路)【转】

    Java源码阅读的真实体会(一种学习思路)   刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+ ...

  3. 如何阅读Java源码 阅读java的真实体会

    刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我觉得最核心有三点:技术基础+强烈的求知欲+耐心.   说到技术基础,我打个比 ...

  4. [收藏] Java源码阅读的真实体会

    收藏自http://www.iteye.com/topic/1113732 刚才在论坛不经意间,看到有关源码阅读的帖子.回想自己前几年,阅读源码那种兴奋和成就感(1),不禁又有一种激动. 源码阅读,我 ...

  5. JDK 1.8源码阅读 ArrayList

    一,前言 ArrayList是Java开发中使用比较频繁的一个类,通过对源码的解读,可以了解ArrayList的内部结构以及实现方法,清楚它的优缺点,以便我们在编程时灵活运用. 二,ArrayList ...

  6. 【JDK1.8】JDK1.8集合源码阅读——ArrayList

    一.前言 在前面几篇,我们已经学习了常见了Map,下面开始阅读实现Collection接口的常见的实现类.在有了之前源码的铺垫之后,我们后面的阅读之路将会变得简单很多,因为很多Collection的结 ...

  7. java源码阅读Hashtable

    1类签名与注释 public class Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, C ...

  8. Java源码阅读Stack

    Stack(栈)实现了一个后进先出(LIFO)的数据结构.该类继承了Vector类,是通过调用父类Vector的方法实现基本操作的. Stack共有以下五个操作: put:将元素压入栈顶. pop:弹 ...

  9. Java源码阅读之ArrayList

    基于jdk1.8的ArrayList源码分析. 实现List接口最常见的大概就四种,ArrayList, LinkedList, Vector, Stack实现,今天就着重看一下ArrayList的源 ...

随机推荐

  1. 常用shell脚本命令

    常用shell脚本命令 1.显示包含文字aaa的下一行的内容: sed -n '/aaa/{n;p;}' filename 2.删除当前行与下一行的内容: sed -i '/aaa/{N;d;}' f ...

  2. 有趣的数(number)

    有趣的数(number) 题目描述 这些天 nodgd 在研究一类有趣的数.定义函数 f(n) f(n) f(n) 表示 n n n 在十进制表示下的数字之和.如果一个正整数 n n n 满足 f(n ...

  3. Heine-Borel定理

    前:开始学数学..来写写理解和补充吧.. 书:M.A.Armstrong著<Basic Topology> Heine-Borel定理:实轴上闭区间是紧集. 证法(1)延伸法: 思想 闭区 ...

  4. iOS-android-windowsphone等移动终端平台开发流程图

    到了公司后,半个月时间就是在熟悉下面这张图里的流程, 项目流程图:     下面是我对这张图的一些理解:        

  5. C++自带栈与队列_stack_queue_C++

    栈和队列我们可以用C++里自带的函数使用,就不必手写了 1.栈,需要开头文件 #include<stack>  定义一个栈s:stack<int> s; 具体操作: s.emp ...

  6. session和xsrf

    1.pip install pycket 2.pip install redis 防止xsrf攻击只需在模板form标签加入: {% module xsrf_form_html() %} <!D ...

  7. [Oracle] 关系型数据库排序算法和数据结构以及关联查询

    关系型数据库排序算法和数据结构以及关联查询 1. Merge sort 理解merge sort算法将有助于更好地理解数据库join操作 - merge join 算法逻辑 将2个有序的大小为N/2的 ...

  8. python update数据

    #!/usr/bin/env python # -*- coding:utf-8 -*- # @Time : 2017/11/23 23:57 # @Author : lijunjiang # @Fi ...

  9. Nginx 兼容IE8

    前言 前段时间由于业务需要,在服务器上新增一个服务专门接收各个门店的业务结算数据,接口文档指明需要使用https协议.这本不是什么问题,因为之前服务器已经有配置过https.但等到服务部署之后才发现这 ...

  10. 【linux高级程序设计】(第十三章)Linux Socket网络编程基础 3

    使用之前的函数实现的简单聊天程序 TCP协议 双方实时发送/接收消息 实现后的问题: 可能是我虚拟机的IP地址配得有问题吧.在一台电脑上面开两个终端,用127.0.0.1的IP收发可以互通.但是两个虚 ...