适合新手的集合ArrayList基础入门

简单介绍:

ArrayList是Java中最常用的数据结构之一,底层是以数组(Object类型)的形式储存数据。它是一个动态数组,可以自动调整其大小以容纳更多元素实现了List接口,因此具有List接口的所有功能。

ArrayList是基于索引的数据结构,它可以快速地访问任何一个元素,因为它使用索引值来直接访问元素,而不是像链表那样需要遍历元素。这使得ArrayList在频繁读取操作的场景下非常高效。

ArrayList的特点如下:

  1. 动态调整大小:当添加的元素超过了当前ArrayList的容量时,它会自动扩容以容纳更多的元素。

  2. 随机访问:由于ArrayList是基于数组实现的,所以可以通过索引值直接访问任意位置的元素,具有很高的读取性能。

  3. 插入和删除效率低:由于需要进行元素的移动,所以在中间位置插入或删除元素的效率相对较低。

  4. 允许重复元素:ArrayList允许存储重复的元素,即同一个值可以出现在多个位置。

  5. 线程不安全:ArrayList不是线程安全的,如果需要在多线程环境下使用,需要通过外部同步机制来确保线程安全。

  6. 灵活的存储类型:虽然ArrayList通常用于存储同一种类型的元素,但它实际上可以接受任何类型的对象,包括原始数据类型。

在使用ArrayList时,需要注意以下几点:

  • 初始容量:在创建ArrayList时,可以通过构造函数指定其初始容量,这有助于减少后续的扩容操作,提高性能。
  • 扩容机制:当添加的元素数量超过当前容量时,ArrayList会自动扩容,通常是将容量翻倍。
  • 泛型:为了提高类型安全性,建议使用泛型来声明ArrayList,这样可以在编译时检查类型错误。
  • 遍历方式:可以使用for循环、迭代器或增强for循环来遍历ArrayList中的元素。

总的来说,ArrayList是一种功能强大且常用的数据结构,适用于需要频繁读取元素的场景。

ArrayList方法:

ArrayList实现了和List接口,这意味着它可以进行集合操作,如添加、删除和检索元素。
下面是List方法关于ArrayList的使用

add(E e):将指定的元素添加到列表的尾部。
add(int index, E element):在列表的指定位置插入指定元素,并移动当前位置及以下的元素。
addAll(Collection c):将指定集合中的所有元素添加到列表的尾部。
addAll(int index, Collection c):从指定位置开始,将指定集合中的所有元素插入列表中。
remove(Object o):移除列表中第一次出现的指定元素(如果存在)。
remove(int index):移除列表中指定位置的元素,并返回被移除的元素。
get(int index):返回列表中指定位置的元素。
set(int index, E element):用指定的元素替换列表中指定位置的元素。
indexOf(Object o):返回此列表中首次出现的指定元素的索引,或如果列表不包含元素,则返回 -1。
lastIndexOf(Object o):返回此列表中最后出现的指定元素的索引,或如果列表不包含元素,则返回 -1。
subList(int fromIndex, int toIndex):返回列表中指定的 fromIndex(包括)和 toIndex(不包括)之间的视图。

此外还有ArrayList自己实现的一些实用性的方法:

clear()用于清除列表
isEmpty()用于检查列表是否为空
size()用于获取列表的大小
iterator()用于获取列表的迭代器

ArrayList的三种构造器

1:无参构造器

//默认大小是10
源码:

    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

构建:

这里是引用

可见初始是一个空数组

2:.带单个整型参数的构造器(可以初始数组的大小)

    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }

这种构造器允许我们指定ArrayList的初始容量。这在我们知道将要存储大量元素且希望提高性能时非常有用,因为它可以减少数组动态扩容的次数。

3:带有Collection参数的构造器

    public ArrayList(Collection<? extends E> c) {
        elementData = c.toArray();
        if ((size = elementData.length) != 0) {
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if (elementData.getClass() != Object[].class)
                elementData = Arrays.copyOf(elementData, size, Object[].class);
        } else {
            // replace with empty array.
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }

例子:

    public static void main(String[] args) {
        ArrayList<Integer> arrayList1 = new ArrayList<>();
        ArrayList<Number> arrayList2 = new ArrayList<>(arrayList1);
    }

解释说明:对public ArrayList(Collection<? extends E> c)中的Collection<? extends E> c 分析将其分为两部分看待
1:Collection c
c的类型为Collection,也就是说传入的参数类型必须是Collection或其子类,而arrayList1的类型正是ArrayList为Collection的子类(下面是继承关系图)

在这里插入图片描述
2:<? extends E> c)
那例子讲解arrayList1的泛型为Integer,arrayList2的泛型为Number也就是说在构建arrayList2对象时《E》便是《Number》所以传入的参数arrayList1的泛型类型继承了E,则arrayList1的泛型,必须是E(Number)或其子类(Integer)。

带有Collection参数的构造器的作用:

创建一个ArrayList,并将传入的集合中的元素复制到这个新的ArrayList中**。这个构造器的使用场景包括但不限于:

  • 从一个集合到另一个集合的数据迁移:当你需要将一个集合中的数据转移到一个新的ArrayList时,这个构造器非常有用。它允许你保持原有集合不变,同时在新的ArrayList中进行操作,这在需要对集合数据进行独立处理时尤其有用。
  • 集合的深拷贝:使用这个构造器可以创建一个包含原集合所有元素的新列表,这是一种深拷贝。这意味着对新列表的修改不会影响到原始集合,反之亦然。
  • 初始化具有初始元素的ArrayList:如果你有一个现有的集合,并且想要创建一个ArrayList,其中包含这些初始元素,这个构造器可以简化这个过程。

需要注意的是,这个构造器内部使用了toArray()方法来将集合转换为数组,然后再将数组中的元素添加到ArrayList中。这种方法比直接添加每个元素更高效,因为它减少了迭代次数。此外,如果传入的集合本身是ArrayList,那么这个构造器会利用ArrayList的elementData数组属性来存储数据,这样做可以避免额外的数组创建和数据复制。

在实际使用中,这个构造器提供了一种方便的方式来创建和初始化ArrayList,尤其是当你已经有了一个集合,并且希望在ArrayList中保留或处理这些数据时。

举个栗子:从一个集合到另一个集合的数据迁移*

    public static void main(String[] args) {
        ArrayList<Integer> arrayList1 = new ArrayList<>();
        arrayList1.add(1);
        arrayList1.add(2);
        arrayList1.add(3);
        ArrayList<Number> arrayList2 = new ArrayList<>(arrayList1);
        arrayList2.add(4);
        System.out.println(arrayList1);
        System.out.println(arrayList2);
        arrayList1.set(0,666);
        System.out.println(arrayList1);
        System.out.println(arrayList2);
    }

在这里插入图片描述

分析:为浅拷贝所以修改arrayList1时arrayList2并不会改变

注意切割方法:subList(int fromIndex, int toIndex)

想想输出结果是什么?

    public static void main(String[] args) {
        ArrayList<Integer> arrayList1 = new ArrayList<>();
        arrayList1.add(1);
        arrayList1.add(2);
        arrayList1.add(3);
        arrayList1.add(4);
        List<Integer> integers = arrayList1.subList(0, 2);
        System.out.println(arrayList1);
        System.out.println(integers);
        System.out.println("==========");
        arrayList1.set(0,666);
        System.out.println(arrayList1);
        System.out.println(integers);
    }

切割方法是返回数据的地址所以arrayList1中的数据变了导致切割出的数据跟着变化了。

三种遍历方法

    public static void main(String[] args) {
        ArrayList<Integer> arrayList1 = new ArrayList<>();
        arrayList1.add(1);
        arrayList1.add(2);
        arrayList1.add(3);
        arrayList1.add(4);
        //1:直接打印
        System.out.println(arrayList1);
        //2:普通for循环
        for (int i = 0; i < arrayList1.size(); i++) {
            System.out.print(arrayList1.get(i));
        }
        System.out.println();
        //3:for -each
        for (Integer x:arrayList1){
            System.out.print(x);
        }
        System.out.println();
        //4:迭代器
        Iterator<Integer> iterator = arrayList1.iterator();
        while (iterator.hasNext()){
            System.out.print(iterator.next());
        }
        System.out.println();
    }

迭代器

在Java中,迭代器(Iterator)是一个对象,它的工作是遍历并选择序列中的对象,用于以标准方式遍历任何集合对象。
删除元素:除了遍历元素外,迭代器还提供了一个remove()方法,我们可以使用这个方法来删除当前元素。需要注意的是,我们不能在没有调用next()方法的情况下直接调用remove()方法,否则会抛出IllegalStateException异常。
代码演示

import java.util.ArrayList;
import java.util.Iterator;

public class IteratorExample {
    public static void main(String[] args) {
        ArrayList<Integer> numbers = new ArrayList<>();
        numbers.add(1);
        numbers.add(2);
        numbers.add(3);
        numbers.add(4);
        numbers.add(5);
        Iterator<Integer> iterator = numbers.iterator();

        // 使用迭代器遍历并删除偶数元素
        while (iterator.hasNext()) {
            int number = iterator.next();
            if (number % 2 == 0) {
                iterator.remove(); // 删除当前元素
            }
        }
        // 输出修改后的ArrayList
        System.out.println(numbers);
    }
}

总的来说,迭代器提供了一种高效且灵活的方式来遍历和修改集合中的元素。在处理大型集合时,使用迭代器可以大大提高代码的效率和可读性。

迭代器的遍历解析

1.可以将迭代器比作一个指针,原本指向集合的第一个位置

        Iterator<Integer> iterator = arrayList1.iterator();//得到一个迭代器
        while (iterator.hasNext()){//该步骤是判断是否存在数据
            System.out.print(iterator.next());//这一步是将迭代器指向的数据打印,同时将迭代器指向下一个数据的位置
        }

2.针对于ArrayList还有其特有的迭代器ListIterator是Iterator的子类有
ListIterator相较于Iterator具有更高级的功能,主要体现在遍历方向、添加元素和索引定位上。以下是它们之间的主要区别:

  1. 遍历方向:Iterator只能单向向前遍历集合,而ListIterator则可以进行双向遍历,即可以向前也可以向后遍历集合。
  2. 添加元素:ListIterator提供了add方法,允许在遍历过程中向List中添加对象,这是Iterator所不具备的功能。
  3. 索引定位:ListIterator可以获取当前遍历的索引位置,通过nextIndex()和previousIndex()方法来实现,这为操作集合提供了更多的灵活性。Iterator则没有提供这样的功能。

总的来说,ListIterator提供了比Iterator更为丰富的功能,特别是在需要双向遍历和修改列表时。然而,如果只需要单向遍历并且不需要修改集合,使用Iterator就足够了。在选择使用哪种迭代器时,应根据具体需求和集合类型来决定。

代码演示:

反向遍历

public static void main(String[] args) {
    // 创建一个ArrayList
    List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
    // 使用ListIterator遍历集合
    System.out.println("使用ListIterator遍历集合:");
    ListIterator<Integer> listIterator = list.listIterator();
    while (listIterator.hasNext()) {
        Integer element = listIterator.next();
        System.out.print(element);
    }
    System.out.println();
    // 使用ListIterator反向遍历集合
    System.out.println("使用ListIterator反向遍历集合:");
    while (listIterator.hasPrevious()) {
        Integer element = listIterator.previous();
        System.out.print(element);
    }
}

在这里插入图片描述

add方法

    public static void main(String[] args) {
        // 创建一个ArrayList
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);

        // 使用ListIterator遍历集合并添加元素
        System.out.println("原始列表:" + list);
            ListIterator<Integer> listIterator = list.listIterator();
        while (listIterator.hasNext()) {
            Integer element = listIterator.next();
            if (element.equals(2)) {
                listIterator.add(6); // 在2之后添加6
            }
        }
        System.out.println(list);
    }

在这里插入图片描述

  • 41
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值