Java集合系列之ArrayList

来源:互联网 发布:预告片 知乎 编辑:程序博客网 时间:2024/05/22 00:39

Java集合系列之ArrayList


开篇前言--ArrayList中的基本方法

前面的博文中,小编主要简单介绍Java集合的总体架构,在接下来的博文中,小编将详细介绍里面的各个类,通过demo、对比,来对java集合类进行更加深入的理解和认识,希望可以帮助有有需要的小伙伴们`(*∩_∩*)′,不足之处,还请小伙伴们多多指教哦`(*∩_∩*)′。今天这篇博文,小编主要介绍List接口中的ArrayList集合,ArrayList即数组列表,so,她肯定和数组有一定的关系,我们知道List集合的特征有两个,一个是有序;第二个List里面的集合可以重复,既然ArrayList实现了List接口,那么毫无疑问,她肯定也存在这两个特征,我们来看一个简单的demo。新建一个class,命名为ArrayListTest,编写相关代码,如下所示:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">package j2se.demo;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. public class ArrayListTest {  
  6.     public static void main(String[] args) {  
  7.         ArrayList arrayList = new ArrayList();  
  8.         arrayList.add("hello");  
  9.         arrayList.add("world");  
  10.         arrayList.add("java");  
  11.           
  12.           
  13.         String s1=(String) arrayList.get(0);  
  14.         String s2=(String)arrayList.get(1);  
  15.         String s3=(String)arrayList.get(2);  
  16.       
  17.           
  18.         System.out.println(s1);  
  19.         System.out.println(s2);  
  20.         System.out.println(s3);  
  21.       
  22.     }  
  23.   
  24. }  
  25. </span>  
运行效果如下所示:

以上是ArrayList的基本用法,接着,我们来修改代码,ArrayList可以添加重复的元素,我们来看下面的代码部分:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">package j2se.demo;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. public class ArrayListTest {  
  6.     public static void main(String[] args) {  
  7.         ArrayList arrayList = new ArrayList();  
  8.         arrayList.add("hello");  
  9.         arrayList.add("world");  
  10.         arrayList.add("java");  
  11.         arrayList.add("java");  
  12.           
  13.         String s1=(String) arrayList.get(0);  
  14.         String s2=(String)arrayList.get(1);  
  15.         String s3=(String)arrayList.get(2);  
  16.         String s4=(String)arrayList.get(3);  
  17.       
  18.           
  19.         System.out.println(s1);  
  20.         System.out.println(s2);  
  21.         System.out.println(s3);  
  22.         System.out.println(s4);  
  23.       
  24.     }  
  25.   
  26. }  
  27. </span>  
运行效果如下所示:

通过运行结果我们知道,说明第二个“java”已经添加进去了,我们发现,ArrayList是通过add进行添加的操作,通过get方法取出来;我们接着来看,size这个方法,返回列表中元素的个数;可是呢,取数据的时候一个一个取,非常的麻烦,所以,我们可以写一个循环,如下所示:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">package j2se.demo;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. public class ArrayListTest {  
  6.     public static void main(String[] args) {  
  7.         ArrayList arrayList = new ArrayList();  
  8.         arrayList.add("hello");  
  9.         arrayList.add("world");  
  10.         arrayList.add("java");  
  11.         arrayList.add("java");  
  12.           
  13.         String s1=(String) arrayList.get(0);  
  14.         String s2=(String)arrayList.get(1);  
  15.         String s3=(String)arrayList.get(2);  
  16.         String s4=(String)arrayList.get(3);  
  17.       
  18.           
  19.         System.out.println(s1);  
  20.         System.out.println(s2);  
  21.         System.out.println(s3);  
  22.         System.out.println(s4);  
  23.           
  24.         System.out.println("----------");  
  25.           
  26.         for(int i = 0 ;i<arrayList.size();i++){  
  27.             System.out.println(arrayList.get(i));  
  28.         }  
  29.       
  30.     }  
  31.   
  32. }  
  33. </span>  
运行效果如下所示:

size方法,用于获取集合中元素的个数,接着我们来看Clear()方法,编写相关代码,如下所示:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">package j2se.demo;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. public class ArrayListTest {  
  6.     public static void main(String[] args) {  
  7.         ArrayList arrayList = new ArrayList();  
  8.         arrayList.add("hello");  
  9.         arrayList.add("world");  
  10.         arrayList.add("java");  
  11.         arrayList.add("java");  
  12.           
  13.         String s1=(String) arrayList.get(0);  
  14.         String s2=(String)arrayList.get(1);  
  15.         String s3=(String)arrayList.get(2);  
  16.         String s4=(String)arrayList.get(3);  
  17.       
  18.           
  19.         System.out.println(s1);  
  20.         System.out.println(s2);  
  21.         System.out.println(s3);  
  22.         System.out.println(s4);  
  23.           
  24.         System.out.println("----------");  
  25.           
  26.         for(int i = 0 ;i<arrayList.size();i++){  
  27.             System.out.println(arrayList.get(i));  
  28.         }  
  29.           
  30.         arrayList.clear();  
  31.         System.out.println(arrayList.size());  
  32.       
  33.     }  
  34.   
  35. }  
  36. </span>  
运行效果如下所示:

接着,我们来看一下isEmpty这个方法,这个方法是用来判断集合中是否有内容的一个方法,编写相关代码,如下所示:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">package j2se.demo;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. public class ArrayListTest {  
  6.     public static void main(String[] args) {  
  7.         ArrayList arrayList = new ArrayList();  
  8.         arrayList.add("hello");  
  9.         arrayList.add("world");  
  10.         arrayList.add("java");  
  11.         arrayList.add("java");  
  12.           
  13.         String s1=(String) arrayList.get(0);  
  14.         String s2=(String)arrayList.get(1);  
  15.         String s3=(String)arrayList.get(2);  
  16.         String s4=(String)arrayList.get(3);  
  17.       
  18.           
  19.         System.out.println(s1);  
  20.         System.out.println(s2);  
  21.         System.out.println(s3);  
  22.         System.out.println(s4);  
  23.           
  24.         System.out.println("----------");  
  25.           
  26.         for(int i = 0 ;i<arrayList.size();i++){  
  27.             System.out.println(arrayList.get(i));  
  28.         }  
  29.           
  30.         arrayList.clear();  
  31.         System.out.println(arrayList.isEmpty());  
  32.       
  33.     }  
  34.   
  35. }  
  36. </span>  
运行效果如下所示:

接着看,如何删除一个元素呢,remove,删除一个根据元素,我们可以根据索引删除,还可以根据具体的对象进行删除,编写相关代码,如下所示:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">package j2se.demo;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. public class ArrayListTest {  
  6.     public static void main(String[] args) {  
  7.         ArrayList arrayList = new ArrayList();  
  8.         arrayList.add("hello");  
  9.         arrayList.add("world");  
  10.         arrayList.add("java");  
  11.         arrayList.add("java");  
  12.           
  13.         String s1=(String) arrayList.get(0);  
  14.         String s2=(String)arrayList.get(1);  
  15.         String s3=(String)arrayList.get(2);  
  16.         String s4=(String)arrayList.get(3);  
  17.       
  18.           
  19.         System.out.println(s1);  
  20.         System.out.println(s2);  
  21.         System.out.println(s3);  
  22.         System.out.println(s4);  
  23.           
  24.         System.out.println("----------");  
  25.           
  26.         for(int i = 0 ;i<arrayList.size();i++){  
  27.             System.out.println(arrayList.get(i));  
  28.         }  
  29.           
  30. //      arrayList.clear();  
  31. //      System.out.println(arrayList.isEmpty());  
  32.           
  33.         arrayList.remove(0);  
  34.         System.out.println("----------");  
  35.         for(int i = 0 ;i<arrayList.size();i++){  
  36.             System.out.println(arrayList.get(i));  
  37.         }  
  38.       
  39.     }  
  40.   
  41. }  
  42. </span>  
运行,如下所示:

除此之外,我们还可以根据索引进行删除,编写相关代码,如下所示:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">package j2se.demo;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. public class ArrayListTest {  
  6.     public static void main(String[] args) {  
  7.         ArrayList arrayList = new ArrayList();  
  8.         arrayList.add("hello");  
  9.         arrayList.add("world");  
  10.         arrayList.add("java");  
  11.         arrayList.add("java");  
  12.           
  13.         String s1=(String) arrayList.get(0);  
  14.         String s2=(String)arrayList.get(1);  
  15.         String s3=(String)arrayList.get(2);  
  16.         String s4=(String)arrayList.get(3);  
  17.       
  18.           
  19.         System.out.println(s1);  
  20.         System.out.println(s2);  
  21.         System.out.println(s3);  
  22.         System.out.println(s4);  
  23.           
  24.         System.out.println("----------");  
  25.           
  26.         for(int i = 0 ;i<arrayList.size();i++){  
  27.             System.out.println(arrayList.get(i));  
  28.         }  
  29.           
  30. //      arrayList.clear();  
  31. //      System.out.println(arrayList.isEmpty());  
  32.           
  33.         arrayList.remove(0);  
  34.         arrayList.remove("java");  
  35.         System.out.println("----------");  
  36.         for(int i = 0 ;i<arrayList.size();i++){  
  37.             System.out.println(arrayList.get(i));  
  38.         }  
  39.       
  40.     }  
  41.   
  42. }  
  43. </span>  
效果如下所示:


接着,我们添加两个元素,打印,indexOf某个对象的索引在哪个位置上,代码如下所示:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">package j2se.demo;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. public class ArrayListTest {  
  6.     public static void main(String[] args) {  
  7.         ArrayList arrayList = new ArrayList();  
  8.         arrayList.add("hello");  
  9.         arrayList.add("world");  
  10.         arrayList.add("java");  
  11.         arrayList.add("java");  
  12.           
  13.         String s1=(String) arrayList.get(0);  
  14.         String s2=(String)arrayList.get(1);  
  15.         String s3=(String)arrayList.get(2);  
  16.         String s4=(String)arrayList.get(3);  
  17.       
  18.           
  19.         System.out.println(s1);  
  20.         System.out.println(s2);  
  21.         System.out.println(s3);  
  22.         System.out.println(s4);  
  23.           
  24.         System.out.println("----------");  
  25.           
  26.         for(int i = 0 ;i<arrayList.size();i++){  
  27.             System.out.println(arrayList.get(i));  
  28.         }  
  29.           
  30. //      arrayList.clear();  
  31. //      System.out.println(arrayList.isEmpty());  
  32.           
  33.         arrayList.remove(0);  
  34.         arrayList.remove("java");  
  35.         System.out.println("----------");  
  36.         for(int i = 0 ;i<arrayList.size();i++){  
  37.             System.out.println(arrayList.get(i));  
  38.         }  
  39.           
  40.         System.out.println("----------");  
  41.         arrayList.add("aaa");  
  42.         arrayList.add("bbb");  
  43.         System.out.println(arrayList.indexOf("aaa"));  
  44.       
  45.     }  
  46.   
  47. }  
  48. </span>  
运行,效果如下所示:


接着,我们新建一个类ArrayListTest1,编写相关代码:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">package j2se.demo;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. public class ArrayListTest1 {  
  6.       
  7.     public static void main(String[] args) {  
  8.         ArrayList list = new ArrayList();  
  9.           
  10.         list.add("hello");  
  11.         list.add(new Integer(2));  
  12.           
  13.         String str=(String)list.get(0);  
  14.         Integer in = (Integer)list.get(1);  
  15.           
  16.         System.out.println(str);  
  17.         System.out.println(in);  
  18.           
  19.     }  
  20.   
  21. }  
  22. </span>  
运行效果如下所示:

ArrayList本身接收的是对象,取出来的时候我们需要把他转换成我们放进去的相应的类型。再来新建一个类ArrayListTest2,如何把集合转成数组呢?编写代码,如下所示:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">package j2se.demo;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. public class ArrayListTest2 {  
  6.     public static void main(String[] args) {  
  7.           
  8.         ArrayList list = new ArrayList();  
  9.         list.add(new Integer(1));  
  10.         list.add(new Integer(2));  
  11.         list.add(new Integer(3));  
  12.         list.add(new Integer(4));  
  13.         list.add(new Integer(5));         
  14.         list.add(new Integer(6));  
  15.           
  16.         /** 
  17.          * 不能将Object[]转换成Integer[] 
  18.          */  
  19.         Object[] in = list.toArray();  
  20.         for(int i = 0 ;i<in.length;i++){  
  21.             System.out.println(((Integer)in[i]).intValue());  
  22.         }  
  23.     }  
  24.   
  25. }  
  26. </span>  
运行如下所示:

ArrayList底层部分源码实现

前面介绍的都是ArrayList的基本方法,小伙伴们可以查询API文档,接着,我们来看ArrayList她自己本身是如何实现的,首先:

a、对于任何一个集合来说,集合中存放的是对象的引用,而不是对象本身。
b、ArrayList底层采用数组实现,当使用不带参数的构成方法生成ArrayList对象的时候,实际上会在底层生成一个长度为10的Object类型数组。简单来说ArrayList内部实现是数组。
c、如果增加的元素个数超过了10个,那么ArrayList底层会新生成一个数组,长度为原来数组的1.5倍+1,然后将原数组的内容复制到新数组中,并且后续增加的内容都会放到新数组当中,当新数组无法容纳增加的元素时,重复该过程。集合中不能放入原生数据类型,只能放置对象的引用,我们需要使用原生数据类型的包装类才能加入到集合当中。我们来看看ArrayList底层的部分源码:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">public class ArrayList<E> extends AbstractList<E>  
  2.         implements List<E>, RandomAccess, Cloneable, java.io.Serializable  
  3. {  
  4.     private static final long serialVersionUID = 8683452581122892189L;  
  5.   
  6.     //设置arrayList默认容量  
  7.     private static final int DEFAULT_CAPACITY = 10;  
  8.   
  9.     //空数组,当调用无参数构造函数的时候默认给个空数组  
  10.     private static final Object[] EMPTY_ELEMENTDATA = {};  
  11.   
  12.     //这才是真正保存数据的数组  
  13.     private transient Object[] elementData;  
  14.   
  15.     //arrayList的实际元素数量  
  16.     private int size;  
  17.   
  18.     //构造方法传入默认的capacity 设置默认数组大小  
  19.     public ArrayList(int initialCapacity) {  
  20.         super();  
  21.         if (initialCapacity < 0)  
  22.             throw new IllegalArgumentException("Illegal Capacity: "+  
  23.                                                initialCapacity);  
  24.         this.elementData = new Object[initialCapacity];  
  25.     }  
  26.   
  27.     //无参数构造方法默认为空数组  
  28.     public ArrayList() {  
  29.         super();  
  30.         this.elementData = EMPTY_ELEMENTDATA;  
  31.     }  
  32.   
  33.     //构造方法传入一个Collection, 则将Collection里面的值copy到arrayList  
  34.     public ArrayList(Collection<? extends E> c) {  
  35.         elementData = c.toArray();  
  36.         size = elementData.length;  
  37.         // c.toArray might (incorrectly) not return Object[] (see 6260652)  
  38.         if (elementData.getClass() != Object[].class)  
  39.             elementData = Arrays.copyOf(elementData, size, Object[].class);  
  40.     }  
  41.       
  42.     //下面主要看看ArrayList 是如何将数组进行动态扩充实现add 和 remove  
  43.       
  44.   
  45.     public boolean add(E e) {  
  46.         ensureCapacityInternal(size + 1);  // Increments modCount!!  
  47.         elementData[size++] = e;  
  48.         return true;  
  49.     }  
  50.   
  51.       
  52.     public void add(int index, E element) {  
  53.         rangeCheckForAdd(index);  
  54.   
  55.         ensureCapacityInternal(size + 1);  // Increments modCount!!  
  56.         System.arraycopy(elementData, index, elementData, index + 1,  
  57.                          size - index);  
  58.         elementData[index] = element;  
  59.         size++;  
  60.     }  
  61.       
  62.     private void ensureCapacityInternal(int minCapacity) {  
  63.         if (elementData == EMPTY_ELEMENTDATA) {  
  64.             minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);  
  65.         }  
  66.   
  67.         ensureExplicitCapacity(minCapacity);  
  68.     }  
  69.       
  70.     private void ensureExplicitCapacity(int minCapacity) {  
  71.         modCount++;  
  72.   
  73.         //超出了数组可容纳的长度,需要进行动态扩展  
  74.         if (minCapacity - elementData.length > 0)  
  75.             grow(minCapacity);  
  76.     }  
  77.       
  78.     //这才是动态扩展的精髓,看到这个方法,ArrayList瞬间被打回原形  
  79.     private void grow(int minCapacity) {  
  80.         int oldCapacity = elementData.length;  
  81.         //设置新数组的容量扩展为原来数组的1.5倍  
  82.         int newCapacity = oldCapacity + (oldCapacity >> 1);  
  83.         //再判断一下新数组的容量够不够,够了就直接使用这个长度创建新数组,   
  84.         //不够就将数组长度设置为需要的长度  
  85.         if (newCapacity - minCapacity < 0)  
  86.             newCapacity = minCapacity;  
  87.         //判断有没超过最大限制  
  88.         if (newCapacity - MAX_ARRAY_SIZE > 0)  
  89.             newCapacity = hugeCapacity(minCapacity);  
  90.         //将原来数组的值copy新数组中去, ArrayList的引用指向新数组  
  91.         //这儿会新创建数组,如果数据量很大,重复的创建的数组,那么还是会影响效率,  
  92.         //因此鼓励在合适的时候通过构造方法指定默认的capaticy大小  
  93.         elementData = Arrays.copyOf(elementData, newCapacity);  
  94.     }  
  95.       
  96.     private static int hugeCapacity(int minCapacity) {  
  97.         if (minCapacity < 0// overflow  
  98.             throw new OutOfMemoryError();  
  99.         return (minCapacity > MAX_ARRAY_SIZE) ?  
  100.             Integer.MAX_VALUE :  
  101.             MAX_ARRAY_SIZE;  
  102.     }  
  103.       
  104.   
  105. }  
  106. </span>  

so,小伙伴们发现了没有,ArrayList 她骨子里面的本质就是数组, ArrayList就是对数组进行动态的扩展,其add, get , remove 等等操作就是对数组的操作。 ArrayList的一些特性都来源于数组:有序、元素可重复、插入慢、 索引快 等等一系列神马所谓的属性, 有没有一种被欺骗了的赶脚`(*∩_∩*)′。

ArrayList中的遍历

我们来看一下ArrayList中的遍历,ArrayList支持三种遍历方式。

第一种:通过迭代器遍历,即通过Iterator去遍历
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">Integer value = null;  
  2. Iterator iter = list.iterator();  
  3. while (iter.hasNext()) {  
  4.     value = (Integer)iter.next();  
  5. }  
  6. </span>  
第二种:随机访问,通过索引值去遍历,因为ArrayList实现了RandomAccess接口,so,她支持通过索引值去随机访问元素:
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">Integer value = null;  
  2. int size = list.size();  
  3. for (int i=0; i<size; i++) {  
  4.     value = (Integer)list.get(i);          
  5. }  
  6. </span>  

第三种:for循环遍历,如下所示:

[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">Integer value = null;  
  2. for (Integer integ:list) {  
  3.     value = integ;  
  4. }</span>  
接着,我们通过一个demo比较一下这三种遍历方式:
[java] view plain copy print?在CODE上查看代码片派生到我的代码片
  1. <span style="font-family:Comic Sans MS;font-size:18px;">package j2se.demo;  
  2. import java.util.*;  
  3. import java.util.concurrent.*;  
  4.   
  5. /* 
  6.  * @desc ArrayList遍历方式和效率的测试程序。 
  7.  * 
  8.  * @author 丁国华 
  9.  */  
  10. public class ArrayListRandomAccessTest {  
  11.   
  12.     public static void main(String[] args) {  
  13.         List list = new ArrayList();  
  14.         for (int i=0; i<100000; i++)  
  15.             list.add(i);  
  16.         iteratorThroughRandomAccess(list) ;  
  17.         iteratorThroughIterator(list) ;  
  18.         iteratorThroughFor2(list) ;  
  19.       
  20.     }  
  21.   
  22.     private static void isRandomAccessSupported(List list) {  
  23.         if (list instanceof RandomAccess) {  
  24.             System.out.println("RandomAccess implemented!");  
  25.         } else {  
  26.             System.out.println("RandomAccess not implemented!");  
  27.         }  
  28.   
  29.     }  
  30.   
  31.     public static void iteratorThroughRandomAccess(List list) {  
  32.   
  33.         long startTime;  
  34.         long endTime;  
  35.         startTime = System.currentTimeMillis();  
  36.         for (int i=0; i<list.size(); i++) {  
  37.             list.get(i);  
  38.         }  
  39.         endTime = System.currentTimeMillis();  
  40.         long interval = endTime - startTime;  
  41.         System.out.println("iteratorThroughRandomAccess:" + interval+" ms");  
  42.     }  
  43.   
  44.     public static void iteratorThroughIterator(List list) {  
  45.   
  46.         long startTime;  
  47.         long endTime;  
  48.         startTime = System.currentTimeMillis();  
  49.         for(Iterator iter = list.iterator(); iter.hasNext(); ) {  
  50.             iter.next();  
  51.         }  
  52.         endTime = System.currentTimeMillis();  
  53.         long interval = endTime - startTime;  
  54.         System.out.println("iteratorThroughIterator:" + interval+" ms");  
  55.     }  
  56.   
  57.   
  58.     public static void iteratorThroughFor2(List list) {  
  59.   
  60.         long startTime;  
  61.         long endTime;  
  62.         startTime = System.currentTimeMillis();  
  63.         for(Object obj:list);  
  64.         endTime = System.currentTimeMillis();  
  65.         long interval = endTime - startTime;  
  66.         System.out.println("iteratorThroughFor2:" + interval+" ms");  
  67.     }  
  68. }  
  69. </span>  

运行效果,如下所示:


由此可见,遍历ArrayList时,使用随机访问(即,通过索引序号访问)效率最高,而使用迭代器的效率最低!

ArrayList的优缺点

接着,我们来看一下ArrayList的优缺点:

从上面的几个过程总结一下ArrayList的优缺点。ArrayList的优点如下:
a、ArrayList底层以数组实现,是一种随机访问模式,再加上它实现了RandomAccess接口,因此查找速度快;
b、ArrayList在顺序添加一个元素的时候非常方便,只是往数组里面添加了一个元素而已;
ArrayList的缺点:
a、删除元素的时候,涉及到一次元素复制,如果要复制的元素很多,那么就会比较耗费性能
b、插入元素的时候,涉及到一次元素复制,如果要复制的元素很多,那么就会比较耗费性能
因此,ArrayList比较适合顺序添加、随机访问的场景。在后面的博文中,小编将介绍LinkedList,等介绍完LinkedList之后,我们把她们两个放在一起进行对比。

     ArrayList线程问题

再说ArrayList线程问题之前,我们需要了解一下,什么是线程安全?什么是线程不安全?线程安全就是多线程访问的时候,采用了加锁机制,当一个线程访问该类的某个数据的时候,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可以使用,不会出现数据不一致或者数据污染。 线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。那么为什么ArrayList为什么线程不安全呢?我们知道ArrayList在添加一个元素的时候,需要两个步骤,第一步在Items[Size]的位置存放此元素,第二步增大Size的值,在单线程运行的情况,比如两个苹果两个人吃,一个人吃一个,这个是并发的,互不影响,但是如果一个人吃两个苹果,要保证同时吃完,就需要这个苹果吃一点,停下来再去吃一点另一个苹果,既然Add方法内部是需要分两步走,那就是线程A在0的位置赋了一个值,然后停下来去B线程ArrayList 0的位置又赋了一个值,其实是重复在一个位置赋值,然后回到A线程,执行Size增加,也就是ArrayList的大小增加了,原来Size是1,现在变成2,然后停下来继续执行线程B,又增加了一个空间位置,size大小就变成了3,结果就是0的位置有值,1和2的索引位置都没有值实际大小是3,跟想要的结果0和1赋不同的值,结果不对,so线程不安全。那么我们如何解决ArrayList中线程不安全的问题呢?

a、继承Arraylist,然后重写或按需求编写自己的方法,这些方法要写成synchronized,在这些synchronized的方法中调用ArrayList的方法。
b、List list = Collections.synchronizedList(new ArrayList());

    小编寄语:该博文,小编主要介绍了List接口实现中的ArrayList集合,通过讲解ArrayList基本方法,加上相关的demo进行联系,接着介绍ArrayList的底层相关源码,满满的都是套路,有么有`(*∩_∩*)′,接着介绍了ArrayList集合中的遍历,ArrayList中的优缺点以及线程问题,ArrayList支持自动改变大小的功能,灵活的插入和删除元素,但是ArrayList跟一般的数组比起来,速度上稍逊风骚,今天的arrayList介绍到这里就要跟小伙伴们再见了,在下篇博文中小编就介绍LinkedList,尽请期待`(*∩_∩*)′!


 
 
0 0