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

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

package j2se.demo;import java.util.ArrayList;public class ArrayListTest {public static void main(String[] args) {ArrayList arrayList = new ArrayList();arrayList.add("hello");arrayList.add("world");arrayList.add("java");String s1=(String) arrayList.get(0);String s2=(String)arrayList.get(1);String s3=(String)arrayList.get(2);System.out.println(s1);System.out.println(s2);System.out.println(s3);}}

运行效果如下所示:

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

package j2se.demo;import java.util.ArrayList;public class ArrayListTest {public static void main(String[] args) {ArrayList arrayList = new ArrayList();arrayList.add("hello");arrayList.add("world");arrayList.add("java");arrayList.add("java");String s1=(String) arrayList.get(0);String s2=(String)arrayList.get(1);String s3=(String)arrayList.get(2);String s4=(String)arrayList.get(3);System.out.println(s1);System.out.println(s2);System.out.println(s3);System.out.println(s4);}}

运行效果如下所示:

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

package j2se.demo;import java.util.ArrayList;public class ArrayListTest {public static void main(String[] args) {ArrayList arrayList = new ArrayList();arrayList.add("hello");arrayList.add("world");arrayList.add("java");arrayList.add("java");String s1=(String) arrayList.get(0);String s2=(String)arrayList.get(1);String s3=(String)arrayList.get(2);String s4=(String)arrayList.get(3);System.out.println(s1);System.out.println(s2);System.out.println(s3);System.out.println(s4);System.out.println("----------");for(int i = 0 ;i<arrayList.size();i++){System.out.println(arrayList.get(i));}}}

运行效果如下所示:

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

package j2se.demo;import java.util.ArrayList;public class ArrayListTest {public static void main(String[] args) {ArrayList arrayList = new ArrayList();arrayList.add("hello");arrayList.add("world");arrayList.add("java");arrayList.add("java");String s1=(String) arrayList.get(0);String s2=(String)arrayList.get(1);String s3=(String)arrayList.get(2);String s4=(String)arrayList.get(3);System.out.println(s1);System.out.println(s2);System.out.println(s3);System.out.println(s4);System.out.println("----------");for(int i = 0 ;i<arrayList.size();i++){System.out.println(arrayList.get(i));}arrayList.clear();System.out.println(arrayList.size());}}

运行效果如下所示:

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

package j2se.demo;import java.util.ArrayList;public class ArrayListTest {public static void main(String[] args) {ArrayList arrayList = new ArrayList();arrayList.add("hello");arrayList.add("world");arrayList.add("java");arrayList.add("java");String s1=(String) arrayList.get(0);String s2=(String)arrayList.get(1);String s3=(String)arrayList.get(2);String s4=(String)arrayList.get(3);System.out.println(s1);System.out.println(s2);System.out.println(s3);System.out.println(s4);System.out.println("----------");for(int i = 0 ;i<arrayList.size();i++){System.out.println(arrayList.get(i));}arrayList.clear();System.out.println(arrayList.isEmpty());}}

运行效果如下所示:

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

package j2se.demo;import java.util.ArrayList;public class ArrayListTest {public static void main(String[] args) {ArrayList arrayList = new ArrayList();arrayList.add("hello");arrayList.add("world");arrayList.add("java");arrayList.add("java");String s1=(String) arrayList.get(0);String s2=(String)arrayList.get(1);String s3=(String)arrayList.get(2);String s4=(String)arrayList.get(3);System.out.println(s1);System.out.println(s2);System.out.println(s3);System.out.println(s4);System.out.println("----------");for(int i = 0 ;i<arrayList.size();i++){System.out.println(arrayList.get(i));}//        arrayList.clear();
//      System.out.println(arrayList.isEmpty());arrayList.remove(0);System.out.println("----------");for(int i = 0 ;i<arrayList.size();i++){System.out.println(arrayList.get(i));}}}

运行,如下所示:

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

package j2se.demo;import java.util.ArrayList;public class ArrayListTest {public static void main(String[] args) {ArrayList arrayList = new ArrayList();arrayList.add("hello");arrayList.add("world");arrayList.add("java");arrayList.add("java");String s1=(String) arrayList.get(0);String s2=(String)arrayList.get(1);String s3=(String)arrayList.get(2);String s4=(String)arrayList.get(3);System.out.println(s1);System.out.println(s2);System.out.println(s3);System.out.println(s4);System.out.println("----------");for(int i = 0 ;i<arrayList.size();i++){System.out.println(arrayList.get(i));}//       arrayList.clear();
//      System.out.println(arrayList.isEmpty());arrayList.remove(0);arrayList.remove("java");System.out.println("----------");for(int i = 0 ;i<arrayList.size();i++){System.out.println(arrayList.get(i));}}}

效果如下所示:


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

package j2se.demo;import java.util.ArrayList;public class ArrayListTest {public static void main(String[] args) {ArrayList arrayList = new ArrayList();arrayList.add("hello");arrayList.add("world");arrayList.add("java");arrayList.add("java");String s1=(String) arrayList.get(0);String s2=(String)arrayList.get(1);String s3=(String)arrayList.get(2);String s4=(String)arrayList.get(3);System.out.println(s1);System.out.println(s2);System.out.println(s3);System.out.println(s4);System.out.println("----------");for(int i = 0 ;i<arrayList.size();i++){System.out.println(arrayList.get(i));}//      arrayList.clear();
//      System.out.println(arrayList.isEmpty());arrayList.remove(0);arrayList.remove("java");System.out.println("----------");for(int i = 0 ;i<arrayList.size();i++){System.out.println(arrayList.get(i));}System.out.println("----------");arrayList.add("aaa");arrayList.add("bbb");System.out.println(arrayList.indexOf("aaa"));}}

运行,效果如下所示:

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

package j2se.demo;import java.util.ArrayList;public class ArrayListTest1 {public static void main(String[] args) {ArrayList list = new ArrayList();list.add("hello");list.add(new Integer(2));String str=(String)list.get(0);Integer in = (Integer)list.get(1);System.out.println(str);System.out.println(in);}}

运行效果如下所示:

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

package j2se.demo;import java.util.ArrayList;public class ArrayListTest2 {public static void main(String[] args) {ArrayList list = new ArrayList();list.add(new Integer(1));list.add(new Integer(2));list.add(new Integer(3));list.add(new Integer(4));list.add(new Integer(5));       list.add(new Integer(6));/*** 不能将Object[]转换成Integer[]*/Object[] in = list.toArray();for(int i = 0 ;i<in.length;i++){System.out.println(((Integer)in[i]).intValue());}}}

运行如下所示:

ArrayList底层部分源码实现

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

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

public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{private static final long serialVersionUID = 8683452581122892189L;//设置arrayList默认容量private static final int DEFAULT_CAPACITY = 10;//空数组,当调用无参数构造函数的时候默认给个空数组private static final Object[] EMPTY_ELEMENTDATA = {};//这才是真正保存数据的数组private transient Object[] elementData;//arrayList的实际元素数量private int size;//构造方法传入默认的capacity 设置默认数组大小public ArrayList(int initialCapacity) {super();if (initialCapacity < 0)throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);this.elementData = new Object[initialCapacity];}//无参数构造方法默认为空数组public ArrayList() {super();this.elementData = EMPTY_ELEMENTDATA;}//构造方法传入一个Collection, 则将Collection里面的值copy到arrayListpublic ArrayList(Collection<? extends E> c) {elementData = c.toArray();size = elementData.length;// c.toArray might (incorrectly) not return Object[] (see 6260652)if (elementData.getClass() != Object[].class)elementData = Arrays.copyOf(elementData, size, Object[].class);}//下面主要看看ArrayList 是如何将数组进行动态扩充实现add 和 removepublic boolean add(E e) {ensureCapacityInternal(size + 1);  // Increments modCount!!elementData[size++] = e;return true;}public void add(int index, E element) {rangeCheckForAdd(index);ensureCapacityInternal(size + 1);  // Increments modCount!!System.arraycopy(elementData, index, elementData, index + 1,size - index);elementData[index] = element;size++;}private void ensureCapacityInternal(int minCapacity) {if (elementData == EMPTY_ELEMENTDATA) {minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);}ensureExplicitCapacity(minCapacity);}private void ensureExplicitCapacity(int minCapacity) {modCount++;//超出了数组可容纳的长度,需要进行动态扩展if (minCapacity - elementData.length > 0)grow(minCapacity);}//这才是动态扩展的精髓,看到这个方法,ArrayList瞬间被打回原形private void grow(int minCapacity) {int oldCapacity = elementData.length;//设置新数组的容量扩展为原来数组的1.5倍int newCapacity = oldCapacity + (oldCapacity >> 1);//再判断一下新数组的容量够不够,够了就直接使用这个长度创建新数组, //不够就将数组长度设置为需要的长度if (newCapacity - minCapacity < 0)newCapacity = minCapacity;//判断有没超过最大限制if (newCapacity - MAX_ARRAY_SIZE > 0)newCapacity = hugeCapacity(minCapacity);//将原来数组的值copy新数组中去, ArrayList的引用指向新数组//这儿会新创建数组,如果数据量很大,重复的创建的数组,那么还是会影响效率,//因此鼓励在合适的时候通过构造方法指定默认的capaticy大小elementData = Arrays.copyOf(elementData, newCapacity);}private static int hugeCapacity(int minCapacity) {if (minCapacity < 0) // overflowthrow new OutOfMemoryError();return (minCapacity > MAX_ARRAY_SIZE) ?Integer.MAX_VALUE :MAX_ARRAY_SIZE;}}

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

ArrayList中的遍历

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

第一种:通过迭代器遍历,即通过Iterator去遍历

Integer value = null;
Iterator iter = list.iterator();
while (iter.hasNext()) {value = (Integer)iter.next();
}

第二种:随机访问,通过索引值去遍历,因为ArrayList实现了RandomAccess接口,so,她支持通过索引值去随机访问元素:

Integer value = null;
int size = list.size();
for (int i=0; i<size; i++) {value = (Integer)list.get(i);
}

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

Integer value = null;
for (Integer integ:list) {value = integ;
}

接着,我们通过一个demo比较一下这三种遍历方式:

package j2se.demo;
import java.util.*;
import java.util.concurrent.*;/** @desc ArrayList遍历方式和效率的测试程序。** @author 丁国华*/
public class ArrayListRandomAccessTest {public static void main(String[] args) {List list = new ArrayList();for (int i=0; i<100000; i++)list.add(i);iteratorThroughRandomAccess(list) ;iteratorThroughIterator(list) ;iteratorThroughFor2(list) ;}private static void isRandomAccessSupported(List list) {if (list instanceof RandomAccess) {System.out.println("RandomAccess implemented!");} else {System.out.println("RandomAccess not implemented!");}}public static void iteratorThroughRandomAccess(List list) {long startTime;long endTime;startTime = System.currentTimeMillis();for (int i=0; i<list.size(); i++) {list.get(i);}endTime = System.currentTimeMillis();long interval = endTime - startTime;System.out.println("iteratorThroughRandomAccess:" + interval+" ms");}public static void iteratorThroughIterator(List list) {long startTime;long endTime;startTime = System.currentTimeMillis();for(Iterator iter = list.iterator(); iter.hasNext(); ) {iter.next();}endTime = System.currentTimeMillis();long interval = endTime - startTime;System.out.println("iteratorThroughIterator:" + interval+" ms");}public static void iteratorThroughFor2(List list) {long startTime;long endTime;startTime = System.currentTimeMillis();for(Object obj:list);endTime = System.currentTimeMillis();long interval = endTime - startTime;System.out.println("iteratorThroughFor2:" + interval+" ms");}
}

运行效果,如下所示:

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

ArrayList的优缺点

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

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

     ArrayList线程问题

再说ArrayList线程问题之前,我们需要了解一下,什么是线程安全?什么是线程不安全?线程安全就是多线程访问的时候,采用了加锁机制,当一个线程访问该类的某个数据的时候,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可以使用,不会出现数据不一致或者数据污染。

【Java集合系列】---ArrayList相关推荐

  1. Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例

    转载自  Java 集合系列03之 ArrayList详细介绍(源码解析)和使用示例 第1部分 ArrayList介绍 ArrayList简介 ArrayList 是一个数组队列,相当于 动态数组.与 ...

  2. Java集合系列之四大常用集合(ArrayList、LinkedList、HashSet、HashMap)的用法

    Java集合系列之四大常用集合(ArrayList.LinkedList.HashSet.HashMap)的用法 ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是A ...

  3. Java 集合系列02之 Collection架构

    概要 首先,我们对Collection进行说明.下面先看看Collection的一些框架类的关系图: Java 集合系列02之 Collection架构 Collection是一个接口,它主要的两个分 ...

  4. Java 集合系列06: Vector深入解析

    戳上面的蓝字关注我们哦! 精彩内容 精选java等全套视频教程 精选java电子图书 大数据视频教程精选 java项目练习精选 概论 这是接着以前的文章分享的,这里给出以前的文章的连接,供小伙伴们回顾 ...

  5. Java 集合系列04之 fail-fast总结

    转载自   Java 集合系列04之 fail-fast总结 概要 前面,我们已经学习了ArrayList.接下来,我们以ArrayList为例,对Iterator的fail-fast机制进行了解.内 ...

  6. Java 集合系列目录(Category)

    Java 集合系列目录(Category) 转自:Java 集合系列目录(Category) 01. Java 集合系列01之 总体框架 02. Java 集合系列02之 Collection架构 0 ...

  7. Java 集合系列 16 HashSet

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  8. java集合系列——java集合概述(一)

    在JDK中集合是很重要的,学习java那么一定要好好的去了解一下集合的源码以及一些集合实现的思想! 一:集合的UML类图(网上下载的图片) Java集合工具包位置是java.util.* 二:集合工具 ...

  9. 新手菜鸟 Java 集合系列目录(Category)

    Java 集合系列01之 总体框架 http://www.cnblogs.com/skywang12345/p/3308498.html (笔记:Java集合是java提供的工具包,包含了常用的数据结 ...

  10. Java 集合系列(一)

    Java集合系列文章将以思维导图为主要形式来展示知识点,让零碎的知识形成体系. 这篇文章主要介绍的是[Java 集合的基本知识],即Java 集合简介. 毕业出来一直使用 PHP 进行开发,对于大学所 ...

最新文章

  1. DVWA默认用户名密码
  2. Linux 单用户模式修改密码与救援模式修改密码总结
  3. [转]深刻理解Python中的元类(metaclass)
  4. pl/sql 报ORA-12154: TNS:无法解析指定的连接标志符
  5. string类assign方法
  6. 【经验】广西集体户口迁回农村原籍超级攻略
  7. 威联通NAS通过宝塔面板实现域名统一端口访问
  8. PHP 底层的运行机制与原理
  9. PCIE总线-PCI、PCIE关系及信号定义
  10. 挖掘城市ip_德国卡尔斯草莓农庄:旅游IP打造要创意更要形象!
  11. FireEye开启IPO大幕
  12. 《MySQL技术内幕》读书笔记
  13. 免费——离散数学(左孝凌)课后习题答案
  14. 服务器哪个位置插网线,服务器网线接线图
  15. html 显示 16进制 颜色,16进制颜色(html颜色值)
  16. 如何加声调口诀_汉语拼音声调标注口诀
  17. html转义字符 放大镜,特殊符号
  18. matlab中关于变量名的规定,在MATLAB中,以下变量名命名正确的是()A:052DB:H123C:_12D:1_D...
  19. Win7自动登录,免密码
  20. 鸿蒙轻内核源码分析:文件系统LittleFS

热门文章

  1. 事务的四个特性-ACID
  2. python调整数组顺序使奇数位于偶数前面
  3. 2021-04-17 深入理解SLAM技术 【3】 数学基础概述
  4. docker mysql镜像连接不上_Mysql安装-Docker版
  5. c4d支持mac系统渲染器有哪些_C4D常用的4大主流渲染器如何选择与比较 (OC/RS/VR/阿诺德)...
  6. matlab缩小矩阵尺寸,Matlab中对矩阵使用矩阵尺寸的索引
  7. 解决springboot不扫描@repository的问题
  8. 【自动驾驶】相机标定 疑问总结
  9. java多线程系列(四)---ReentrantLock的使用
  10. [Google Guava] 10-散列