Java中的集合类:ArrayList

Java中的集合类

1、ArrayList

1.1、ArrayList的简介

  ArrayList是Java中的一种集合类,是一种用来进行单值存储的数据结构。所有进行单值存储的类都是实现了Collection接口,ArrayList也不例外,此外该类还继承了AbstractList类和实现了其他的接口:Serializable接口 , Cloneable接口 , Iterable接口 ,List接口, RandomAccess 接口。使用该集合存储数据时,需要进行导包操作,导入的包为:java.util.ArrayList。

  ArrayList的特点是:使用方便且简单、方便进行查询数据和遍历数据,当然相对使用ArrayList进行数据的插入和删除时效率就会低很多,还有一点,ArrayList在多线程的程序中操作的性能很高,但安全性低,这些特点是由ArrayList的底层实现原理所决定的。所以接下来就来介绍ArrayList的底层实现原理,了解ArrayList时如何进行数据存储的,为何会有上述的特点。

1.2、ArrayList的底层实现原理

  ArrayList的底层结构是一个可以进行自动扩容的数组结构,该集合存储数据的方式和数组相差无几:存在下标,每个下标会对应存放一个元素(数据),当元素的数量达到集合现有的最大容量时,ArrayList会实现自动扩容的操作(自动扩大ArrayList集合的容量)。

  因为ArrayLis的底层结构是数组的缘故,所以在查询和遍历时可以使用元素的下标来获取元素,因此执行操作的效率非常高,而在进行增删操作时,当前元素执行完操作之后,该元素之后的元素都需要进行前移或后移的操作,当数据量相当大时,就会导致执行操作的效率非常低

  在多线程程序的操作中,ArrayList采用的是异步处理的操作,因此多个线程使用ArrayList进行数据处理是同时进行,所以性能高,但也因为是异步处理机制,就会导致数据的不安全性。(如果不了解多线程的朋友,可以阅读我这篇文章:“Java多线程技术解析” 进行相关知识的了解)

1.3、ArrayList的相关操作方法

1.3.1、ArrayList的构造方法

  创建ArrayList集合的构造方法有三种:

  1. ArrayList()
  2. ArrayList​(int initialCapacity)
  3. ArrayList(Collection<? extends E> c)

  第一种构造方法是不需要传入任何参数的方式,作用是:创建一个容量为10的ArrayList集合。

  注意:用这种方法刚构建出来的ArrayList的容量是为0的,那为何在上面的作用里我说容量是10,这是因为这种方式创建的容量为0的ArrayList集合在第一次进行存储数据时,会自动把集合的容量扩容成10,所以在Java的API介绍里是容量为10。当然这只是一个小小的科普,是为了和第二种构造方法区分开来,因为第二种构造方法是自己定义ArrayList集合的容量。

  第二种构造方法需要传入一个int类型的参数,参数作用是:指定创建的ArrayList的容量,方法的作用是:创建一个你指定的容量大小的ArrayList集合。

  第三种构造方法需要传入一个实现了Collection接口的集合,方法作用是:将你传入的集合转变成ArrayList集合,ArrayList集合的容量和你传入的集合的容量一致。

  创建的具体Java代码格式如下:

	//这是第一种方式:创建一个默认容量为10的ArrayList集合
	ArrayList<E> list = new ArrayList<>();
	//这是第二种方式:创建一个容量为30的ArrayList集合
	ArrayList<E> list = new ArrayList<>(30);
	//这是第三种方式:将List集合转变为ArrayList集合
	ArrayList<E> list = new ArrayList<>( new List<E>());

  注意:在我的代码中有一个< E>的表示方式,这是代表泛型的表示方式,意义是:你可以自己决定集合中存储什么类型的数据。还有一点,传入的是具体的包装类,比如:int要写成Integer、char要写成Character、其他的不变。

1.3.2、add方法

  该方法有两种使用方式:

  1. void add(int index,E element)
  2. boolean add(E elenemt)

  第一种方式需要传入两个参数,第一个是int类型的参数,表示你指定的下标值;另一个是泛型类型的参数,表示你要存储的数据元素。方法的作用是:在你指定的下标位置添加你传入的数据元素。

  注意:如果该下标存在元素,会把该下标原有的元素和之后的元素都后移一位。

  第二种方式需要传入一个参数,该参数表示你要存储的数据元素,方法的作用是:在集合列表的尾部添加指定的数据元素(和数组一个道理)。使用方法后会返回一个true(不存在添加不了的情况,没有false值)。

  以下是Java代码:

public class Test {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(1,2);
        System.out.println(list.toString());
    }
}

  以下是效果图:

在这里插入图片描述

  效果图可以很清楚的看到添加后的效果,可以展现出这种效果是因为我用了ArrayList中的另一个方法:toString方法,下面就来介绍该方法吧。

1.3.3、toString方法

  使用该方法后会有一个String类型的返回值,使用时无需传入参数,作用是:将ArrayList集合转换成一个String类型的字符串,该字符串的格式为:[元素1,元素2,……,元素n],就如上面的效果图所展示的效果,具体代码参照上面add方法的演示代码。

  当然除了这种方法可以获取到ArrayList集合中的元素外,还可以使用get方法获得你所指定的ArrayList集合内的元素,那下面就来介绍get方法。

1.3.4、get方法

  使用该方法后会有一个泛型类型的返回值,该泛型以你存储的元素类型所决定,使用时需要传入一个int类型的参数,该参数的值表示ArrayList集合的下标,方法的作用是:获取ArrayList集合中下标(为你所指定的)中的元素。Java代码格式为:

  • E get​(int index)

   注意:当index < 0 || index >= size(),该条件满足后会抛出IndexOutOfBoundsException该类异常。

  以下是Java代码:

public class Test1 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        System.out.println(list.toString());
        System.out.println("下标为1的元素为:"+list.get(1));
        System.out.println("下标为3的元素为:"+list.get(3));
    }
}

  以下是效果图:

在这里插入图片描述

  介绍完获取指定位置的元素的方法,接下来介绍修改指定位置的元素的方法:set方法

1.3.5、set方法

  使用该方法后会有一个泛型类型的返回值,该泛型以你存储的元素类型所决定,该返回值代表的是被你替换掉的元素(旧元素),使用方法时需要传入两个参数:第一个是int类型的参数,表示你指定的下标值;另一个是泛型类型的参数,表示你要修改成的新元素。Java代码格式为:

  • E set​(int index, E element)

   注意:当index < 0 || index >= size(),该条件满足后会抛出IndexOutOfBoundsException该类异常。

  以下是Java代码:

public class Test2 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        System.out.println("修改之前的集合内容:"+list.toString());
        Integer set = list.set(2, 5);
        System.out.println("被修改的元素为:"+set);
        System.out.println("修改之后的集合内容:"+list.toString());
    }
}

  以下是效果图:

在这里插入图片描述

  介绍了如何修改指定位置的元素,下面来介绍ArrayList集合中删除元素的方法:remove方法

1.3.6、remove方法

  该方法有两种使用方式:

  1. E remove​(int index)
  2. boolean remove​(Object o)

  第一种方式使用后有一个泛型类型的返回值,该泛型以你存储的元素类型所决定,该返回值代表的是被你删除掉的元素(旧元素),使用时需要传入一个int类型的参数,该参数的值表示ArrayList集合的下标,方法的作用是:删除ArrayList集合中你指定的下标位置的元素。

   注意:index < 0 || index >= size(),该条件满足后会抛出IndexOutOfBoundsException该类异常

  第二种方式使用后会有一个booleam类型的返回值,使用时需要传入一个Object类型的参数,该参数代表的是在ArrayList集合中你想要删除的元素,方法作用是:删除ArrayList集合中你指定的元素,删除成功返回true,不成功返回false(集合中没找到你所指定的元素)。

  以下是Java代码:

public class Test3 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        System.out.println("删除前的集合元素:"+list.toString());
        Integer remove = list.remove(2);
        System.out.println("被删除的元素为:"+remove);
        if(list.remove((Object)4)){
            System.out.println("元素删除成功");
        }else {
            System.out.println("元素删除不成功");
        }
        if(list.remove((Object)6)){
            System.out.println("元素删除成功");
        }else {
            System.out.println("元素删除不成功");
        }
        System.out.println("删除后集合元素:"+list.toString());
    }
}

  以下是效果图:

在这里插入图片描述

  由效果图可以看到我想删除元素为6时,显示的是删除失败,因为集合中没有6这个元素,返回的是false,if-else语句中会执行else中的语句。

  介绍完集合的增、删、改、查这些操作,接下来介绍集合中的遍历方法:for循环、增强for循环(foreach)、使用迭代器遍历的方法。

1.3.7、遍历集合元素的方法

  ArrayList集合中有多种方式可以进行遍历集合的元素,我给大家列举了以下几种:

  1. 使用for循环遍历集合元素
  2. 使用强化for循环遍历集合元素
  3. 使用iterator方法遍历集合元素
  4. 使用listIterator方法遍历集合元素

  第一种方法和数组的遍历是一个道理,在获取下标之后,使用get方法获取对应下标中的元素。

  第二种方法可能有些小伙伴会不知道增强for循环(foreach)是什么,问题不大,我给你们Java代码格式:

	ArrayList<Integer> list = new ArrayList<>();
	foreach( int i:list){
		…………
	}

  从代码中可以看到,我创建了一个存储int类型元素的ArrayList集合,在foreach循环的判断体中我创建了一个和ArrayList集合中的元素的类型一致的变量i,之后的是一个冒号(:),在之后是集合的对象,这就表示用i去映射集合中的每个元素,即用i去拿到集合中的元素,循环的结束条件是:将集合中的所有元素都映射了之后,就会退出循环。

  第三种方法是调用iterator方法获得一个迭代器,该迭代器相当于集合中的指针,遍历集合元素就是获取该指针所指的值。具体使用方式:使用while循环将判断条件写成:迭代器对象调用hasNext方法,判断在下一个指针是否存在,不存在跳出whlie循环,在循环体内使用迭代器对象调用next方法获取下一个指针所指向的元素,这就是执行整个过程。看说明很晕,我直接给个Java代码格式:

		//ArrayList的对象list调用iterator方法获取迭代器,
		//注意:迭代器尖括号中的类型和集合的元素的类型是一致的
		Iterator<Integer> iterator = list.iterator();
        while(iterator.hasNext()/*判断下一个指针是否存在*/){
        	//迭代器对象调用next方法获取指针指向的值
            int i = iterator.next();
            System.out.print(i+" ");
        }

  第四种方法是调用listIterator方法也是获得一个迭代器,遍历的执行过程和iterator方法一致,但调用listIterator方法获得的迭代器中的指针可以往上移,实现集合元素的反向遍历,这是调用iterator方法获得的迭代器不能做到的。具体的使用方式:使用whlie循环将的判断条件写成:listIterator迭代器对象调用hasPrevious方法,判断是否存在上一个指针,不存在跳出循环,循环体中,listIterator迭代器对象调用previous方法获取上一个指针所指的元素,这就是执行过程。Java代码格式为:

ListIterator<Integer> listIterator = list.listIterator();
        while (listIterator.hasNext()){
           int i = listIterator.next();
            System.out.print(i+" ");
        }
         while (listIterator.hasPrevious()/*判断是否存在上一个指针*/){
         	//获取上一个指针所指的元素
            int i = listIterator.previous();
            System.out.print(i+" ");
        }

  注意:一开始是不能往上移动指针的,因为默认的指针位置就是在集合的最顶端的位置,想要再往上移动指针是不可能的。如果想要往上移动指针,那必须把指针先往下移动才可以,不然执行后会抛异常。

  以下是Java代码:

public class Test4 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        System.out.print("使用for循环——集合的元素有:");
        for(int i=0;i< list.size();i++){
            System.out.print(list.get(i)+" ");
        }
        System.out.println();
        System.out.print("使用foreach循环——集合的元素有:");
        for (int i:list  ) {

            System.out.print(i+" ");
        }
        System.out.println();
        System.out.print("使用iterator方法——集合的元素有:");
        Iterator<Integer> iterator = list.iterator();
        while(iterator.hasNext()){
            int i = iterator.next();
            System.out.print(i+" ");
        }
        System.out.println();
        System.out.print("使用listIterator方法——集合的元素有:");
        ListIterator<Integer> listIterator = list.listIterator();
        while (listIterator.hasNext()){
           int i = listIterator.next();
            System.out.print(i+" ");
        }
        System.out.println();
        System.out.print("使用listIterator方法——反向遍历集合的元素有:");
        while (listIterator.hasPrevious()){
            int i = listIterator.previous();
            System.out.print(i+" ");
        }
    }
}

  以下是效果图:

在这里插入图片描述

  这就是常用的几种ArrayList集合的遍历方式,下面来介绍集合中的其他方法

1.3.8、size方法

  使用该方法时会有一个int类型的返回值,该返回值代表集合中的元素个数,使用时不需要传入任何参数,方法作用是:获取集合中的元素个数。

  在使用for循环遍历集合元素时,我就用到了该方法,不知道小伙伴有没有发现:for循环的判断条件我写的就是该方法,没发现的小伙伴可以往上去看看,接下来我就不演示写个方法的具体代码和效果图了,知道了该方法怎么用,作用是什么就可以了。

1.3.9、contains方法

  使用该方法后会有一个boolean类型的返回值,使用时传入一个Object类型的参数,该参数代表是你指定的元素,方法的作用是:判断集合中是否含有你指定的元素,如果有返回true,没有则返回false。

  以下是Java代码:

public class Test5 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        System.out.println("集合中的元素有:"+list.toString());
        if(list.contains(4)){
            System.out.println("集合中有4这个元素");
        }else {
            System.out.println("集合中没有4这个元素");
        }
        if(list.contains(6)){
            System.out.println("集合中有6这个元素");
        }else {
            System.out.println("集合中没有6这个元素");
        }
    }
}

  以下是效果图:

在这里插入图片描述

1.3.10、toArray方法

   该方法有两种使用方式:

  1. < T > T[ ] toArray​(T[ ] e)
  2. Object[ ] toArray(Object[ ] o)

  第一种方法使用后会有一个类型是你自定义类的类型的数组作为返回值,使用时传入一个你自定义类的类型的数组,该数组代表:你指定存放元素的数组,方法的作用是:将ArrayList集合转换成数组,该数组是由你所指定的数组,注意:该数组的容量必须足够大,否则你指定的数组将不生效,方法会自动生成一个新数组去存放。

  第二种方法的作用和第一种一样,都是将集合转换成数组,不同的在于:传入的参数类型是Object类型的数组,生成的也是Object类型的数组。

  toArray方法我也不做过多的演示了,毕竟不是很常用的方法,感兴趣的小伙伴可以自己尝试去敲代码实现效果。

  好了,关于ArrayList集合的相关内容我就介绍的这了,希望文章可以帮助到你们,谢谢支持。

  

相关博文:“Java多线程技术解析”

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值