当前位置:   article > 正文

Java-集合(ArrayList类)_java里面arrlist里面可以存放多少个null

java里面arrlist里面可以存放多少个null

ArrayList注意事项

1)ArrayList集合对象可以添加任意的元素,可以添加null元素,并且可以添加多个null元素;

2)ArrayList是由数组来实现数据存储的;

3)ArrayLiat基本等同于Vector,除了ArrayList是线程不安全的(执行效率高);在多线程情况下不建议使用ArrayList。

  1. package com.pero.list_;
  2. import java.util.ArrayList;
  3. /**
  4. * @author Pero
  5. * @version 1.0
  6. */
  7. public class ArrayListDetail {
  8. public static void main(String[] args) {
  9. //ArrayList线程不安全,源码中方法没有用synchronized修饰
  10. /*
  11. * public boolean add(E e) {
  12. ensureCapacityInternal(size + 1); // Increments modCount!!
  13. elementData[size++] = e;
  14. return true;
  15. }
  16. * */
  17. ArrayList arrayList = new ArrayList();
  18. //可以添加null
  19. arrayList.add(null);
  20. arrayList.add("jack");
  21. //可以添加多个null
  22. arrayList.add(null);
  23. }
  24. }

ArrayList的底层操作机制和源码分析

1)ArrayList中维护了一个Object类型的数组elementData;

2)当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次添加,则扩容elementData为10,如果需要再次扩容,则扩容elementDate为1.5倍;

3)如果使用的是指定容量大小大的有参构造器,则初始elementData容量为指定大小的值,如果需要扩容,则直接扩容elementData为1.5倍。

测试代码:

  1. package com.pero.list_;
  2. import java.util.ArrayList;
  3. /**
  4. * ArrayList的底层操作机制
  5. *
  6. * @author Pero
  7. * @version 1.0
  8. */
  9. public class ArrayListSource {
  10. public static void main(String[] args) {
  11. //使用无参构造器创建一个ArrayList对象
  12. ArrayList arrayList = new ArrayList();
  13. //使用带参数的构造器,给集合赋予初始的空间大小
  14. //ArrayList arrayList1 = new ArrayList(8);
  15. //使用for给arrayList集合添加1-10数据
  16. for (int i = 1; i <= 10; i++) {
  17. arrayList.add(i);
  18. }
  19. //使用for给arrayList集合添加11-15数据
  20. for (int i = 11; i <= 15; i++) {
  21. arrayList.add(i);
  22. }
  23. arrayList.add(100);
  24. arrayList.add(200);
  25. arrayList.add(null);
  26. }
  27. }

执行步骤(无参构造器):

步骤一:执行无参构造器(将一个空的Object类型的数组传给elementData)

  1. public ArrayList() {
  2. this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
  3. }

 ★elementData的定义:

transient Object[] elementData;
 ★DEFAULTCAPACITY_EMPTY_ELEMENTDATA的定义:
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

步骤二:数据装箱(例如int类型转换成Integer类型)

  1. public static Integer valueOf(int i) {
  2. if (i >= IntegerCache.low && i <= IntegerCache.high)
  3. return IntegerCache.cache[i + (-IntegerCache.low)];
  4. return new Integer(i);
  5. }

步骤三:执行arrayList.add(i),添加元素

①执行add(E e)方法:(首先进入ensureCapacityInternal(int minCapacity)方法)

  1. public boolean add(E e) {
  2. ensureCapacityInternal(size + 1); //确认容量是否足够使用
  3. elementData[size++] = e; //先将元素e添加进elementData[size]中,然后在执行size++
  4. return true; //添加成功
  5. }

②执行ensureCapacityInternal(int minCapacity)方法:(将size + 1 的值以minCapacity形式传进calculateCapacity(Object[] elementData, int minCapacity)方法。)

  1. private void ensureCapacityInternal(int minCapacity) {
  2. ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
  3. }

③执行calculateCapacity(Object[] elementData, int minCapacity)方法:(判断elementData是否为初始定义的空数组,如果是则对DEFAULT_CAPACITY与minCapacity进行比较返回最大的那个值;如果elementData不为初始定义的空数组,则直接返回minCapacity。并将结果传入ensureExplicitCapacity(int minCapacity)方法。)

  1. private static int calculateCapacity(Object[] elementData, int minCapacity) {
  2. if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
  3. return Math.max(DEFAULT_CAPACITY, minCapacity);
  4. }
  5. return minCapacity;
  6. }
private static final int DEFAULT_CAPACITY = 10;

④执行ensureExplicitCapacity(int minCapacity)方法:(首先执行modCount++,是记录集合当前被修改的次数,防止有多个线程同时去修改;然后执行判断minCapacity - elementData.length > 0,意思是如果当前所需求的最小的容量比elementData数组的值要大,那么就要执行grow(minCapacity)方法,对数组进行扩容。)

  1. private void ensureExplicitCapacity(int minCapacity) {
  2. modCount++;
  3. // overflow-conscious code
  4. if (minCapacity - elementData.length > 0)
  5. grow(minCapacity);
  6. }

⑤执行grow(int minCapacity)方法:(第一,将原先的elementData数组长度保存为oldCapacity,第二,定义一个新的数组长度newCapacity,大小为老数组长度的1.5倍(oldCapacity + (oldCapacity >> 1),数值右移一位表示原来的数除以二);第三,进行判断newCapacity - minCapacity < 0,如果满足条件则对newCapacity进行重新赋值,例如:无参构造器的elementData初始数组长度为0,0+0/2的值依旧为0,经过判断newCapacity(值为0) - minCapacity(值为10)< 0,然后将minCapacity(值为10)赋值给newCapacity;第四,判断newCapacity的值是否大于MAX_ARRAY_SIZE(值为2147483647),如果满足条件则执行hugeCapacity(minCapacity)方法对newCapacity进行重新赋值,否则执行下一条语句;第五,执行Arrays.copyOf(elementData,newCapacity)方法进行数组拷贝,将原来数组中的数据和扩容后(扩容空间中添加null)再拷贝进elementData数组中。

  1. private void grow(int minCapacity) {
  2. // overflow-conscious code
  3. int oldCapacity = elementData.length;
  4. int newCapacity = oldCapacity + (oldCapacity >> 1);
  5. if (newCapacity - minCapacity < 0)
  6. newCapacity = minCapacity;
  7. if (newCapacity - MAX_ARRAY_SIZE > 0)
  8. newCapacity = hugeCapacity(minCapacity);
  9. // minCapacity is usually close to size, so this is a win:
  10. elementData = Arrays.copyOf(elementData, newCapacity);
  11. }
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
  1. /**
  2. * A constant holding the maximum value an {@code int} can
  3. * have, 2的31次方-1.
  4. */
  5. @Native public static final int MAX_VALUE = 0x7fffffff;(值为2147483647
  1. private static int hugeCapacity(int minCapacity) {
  2. if (minCapacity < 0) // overflow
  3. throw new OutOfMemoryError();
  4. return (minCapacity > MAX_ARRAY_SIZE) ?
  5. Integer.MAX_VALUE :
  6. MAX_ARRAY_SIZE;
  7. }
  1. public static <T> T[] copyOf(T[] original, int newLength) {
  2. return (T[]) copyOf(original, newLength, original.getClass());
  3. }

⑥集合扩容完毕后开始添加元素,执行elementData[size++] = e;然后返回;在容量足够的情况下,执行循环语句。

  1. public boolean add(E e) {
  2. ensureCapacityInternal(size + 1); //确认容量是否足够使用
  3. elementData[size++] = e; //先将元素e添加进elementData[size]中,然后在执行size++
  4. return true; //添加成功
  5. }

步骤四: 当集合空间不足时:进入集合扩容流程:执行ensureCapacityInternal(int minCapacity)方法 -> 执行calculateCapacity(Object[] elementData, int minCapacity)方法 -> 执行ensureExplicitCapacity(int minCapacity)方法 -> 执行grow(int minCapacity)方法(对elementData数组容量扩充为原来的1.5倍) -> 返回。

执行步骤(有参构造器): 

步骤一:执行有参构造器:(对传入实参的数值大小进行判断,如果大于0则创建一个实参数值大小空间的Object数组传给elementData;如果等于零则将EMPTY_ELEMENTDATA(数组空间为0)传给elementData;如果为其他则抛出异常:throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);)

  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. }

步骤二:数据装箱(例如int类型转换成Integer类型)

  1. public static Integer valueOf(int i) {
  2. if (i >= IntegerCache.low && i <= IntegerCache.high)
  3. return IntegerCache.cache[i + (-IntegerCache.low)];
  4. return new Integer(i);
  5. }

步骤三: 执行arrayList.add(i),添加元素

①执行add(E e)方法:(首先进入ensureCapacityInternal(int minCapacity)方法)

  1. public boolean add(E e) {
  2. ensureCapacityInternal(size + 1); //确认容量是否足够使用
  3. elementData[size++] = e; //先将元素e添加进elementData[size]中,然后在执行size++
  4. return true; //添加成功
  5. }

②执行ensureCapacityInternal(int minCapacity)方法:(将size + 1 的值以minCapacity形式传进calculateCapacity(Object[] elementData, int minCapacity)方法。)

  1. private void ensureCapacityInternal(int minCapacity) {
  2. ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
  3. }

③执行calculateCapacity(Object[] elementData, int minCapacity)方法:(判断elementData是否为初始定义的空数组,如果是则对DEFAULT_CAPACITY与minCapacity进行比较返回最大的那个值;如果elementData不为初始定义的空数组,则直接返回minCapacity。并将结果传入ensureExplicitCapacity(int minCapacity)方法。)

  1. private static int calculateCapacity(Object[] elementData, int minCapacity) {
  2. if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
  3. return Math.max(DEFAULT_CAPACITY, minCapacity);
  4. }
  5. return minCapacity;
  6. }
private static final int DEFAULT_CAPACITY = 10;

④执行ensureExplicitCapacity(int minCapacity)方法:(首先执行modCount++,是记录集合当前被修改的次数,防止有多个线程同时去修改;然后执行判断minCapacity - elementData.length > 0,意思是如果当前所需求的最小的容量比elementData数组的值要大,那么就要执行grow(minCapacity)方法,对数组进行扩容。因为初始化集合容量为8,当传入数据1~7时,不对数组进行扩容,不执行grow(minCapacity)方法。)

  1. private void ensureExplicitCapacity(int minCapacity) {
  2. modCount++;
  3. // overflow-conscious code
  4. if (minCapacity - elementData.length > 0)
  5. grow(minCapacity);
  6. }

⑤执行grow(int minCapacity)方法:(第一,将原先的elementData数组长度保存为oldCapacity,第二,定义一个新的数组长度newCapacity,大小为老数组长度的1.5倍(oldCapacity + (oldCapacity >> 1),数值右移一位表示原来的数除以二);第三,进行判断newCapacity - minCapacity < 0,如果满足条件则对newCapacity进行重新赋值,例如:有参构造器指定集合空间为8,扩容后容量为8+4=12>0,不满足条件,执行下一条语句;第四,判断newCapacity的值是否大于MAX_ARRAY_SIZE(值为2147483647),如果满足条件则执行hugeCapacity(minCapacity)方法对newCapacity进行重新赋值,否则执行下一条语句;第五,执行Arrays.copyOf(elementData,newCapacity)方法进行数组拷贝,将原来数组中的数据和扩容后(扩容空间中添加null)再拷贝进elementData数组中。

  1. private void grow(int minCapacity) {
  2. // overflow-conscious code
  3. int oldCapacity = elementData.length;
  4. int newCapacity = oldCapacity + (oldCapacity >> 1);
  5. if (newCapacity - minCapacity < 0)
  6. newCapacity = minCapacity;
  7. if (newCapacity - MAX_ARRAY_SIZE > 0)
  8. newCapacity = hugeCapacity(minCapacity);
  9. // minCapacity is usually close to size, so this is a win:
  10. elementData = Arrays.copyOf(elementData, newCapacity);
  11. }
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
  1. /**
  2. * A constant holding the maximum value an {@code int} can
  3. * have, 2的31次方-1.
  4. */
  5. @Native public static final int MAX_VALUE = 0x7fffffff;(值为2147483647
  1. private static int hugeCapacity(int minCapacity) {
  2. if (minCapacity < 0) // overflow
  3. throw new OutOfMemoryError();
  4. return (minCapacity > MAX_ARRAY_SIZE) ?
  5. Integer.MAX_VALUE :
  6. MAX_ARRAY_SIZE;
  7. }
  1. public static <T> T[] copyOf(T[] original, int newLength) {
  2. return (T[]) copyOf(original, newLength, original.getClass());
  3. }

⑥集合扩容完毕后开始添加元素,执行elementData[size++] = e;然后返回;在容量足够的情况下,执行循环语句。

  1. public boolean add(E e) {
  2. ensureCapacityInternal(size + 1); //确认容量是否足够使用
  3. elementData[size++] = e; //先将元素e添加进elementData[size]中,然后在执行size++
  4. return true; //添加成功
  5. }

步骤四: 当集合空间不足时:进入集合扩容流程:执行ensureCapacityInternal(int minCapacity)方法 -> 执行calculateCapacity(Object[] elementData, int minCapacity)方法 -> 执行ensureExplicitCapacity(int minCapacity)方法 -> 执行grow(int minCapacity)方法(对elementData数组容量扩充为原来的1.5倍) -> 返回。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/766539
推荐阅读
相关标签
  

闽ICP备14008679号