ArrayList 与 LinkedList 的方法及其区别

写在前面: 我是「扬帆向海」,这个昵称来源于我的名字以及女朋友的名字。我热爱技术、热爱开源、热爱编程。技术是开源的、知识是共享的。

这博客是对自己学习的一点点总结及记录,如果您对 Java算法 感兴趣,可以关注我的动态,我们一起学习。

用知识改变命运,让我们的家人过上更好的生活

一、聊聊 LinkedList

1.LinkedList 的底层源码

public class LinkedList<E>
    extends AbstractSequentialList<E>
    implements List<E>, Deque<E>, Cloneable, java.io.Serializable

双链表实现了 List 和Deque接口。 实现所有可选列表操作,并允许所有元素(包括null )。
所有的操作都能像双向列表一样。 索引到列表中的操作将从开始或结束遍历列表,以更接近指定的索引为准。

2.LinkedList 的构造方法

  • LinkedList() 构造一个空列表。
  • LinkedList(Collection<? extends E> c) 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。

3.LinkedList 的常用方法

  • boolean add(E e) 将指定的元素追加到此列表的末尾
  • int size() 返回此列表中的元素数
  • E get(int index) 返回此列表中指定位置的元素
  • E remove(int index) 删除该列表中指定位置的元素
  • void addFirst(E e) 在该列表开头插入指定的元素
  • void addLast(E e) 将指定的元素追加到此列表的末尾
  • E getFirst() 返回此列表中的第一个元素
  • E getLast() 返回此列表中的最后一个元素
  • void push(E e) 将元素推送到由此列表表示的堆栈上
  • E pop() 从此列表表示的堆栈中弹出一个元素

测试代码:

public class LinkedListTest {
    public static void main(String[] args) {

        LinkedList<String> list = new LinkedList<String>();
        // boolean add(E e) 将指定的元素追加到此列表的末尾。
        list.add("aaa");
        list.add("ddd");
        list.add("ccc");
        list.add("111");
        list.add("aaa");
        list.add("eee");

        // int size() 返回此列表中的元素数
        System.out.println(list.size()); // 6
        System.out.println(list); // [aaa, ddd, ccc, 111, aaa, eee]

        // E get(int index) 返回此列表中指定位置的元素。
        System.out.println(list.get(0)); // aaa
        System.out.println(list.get(list.size() - 1)); // eee

        System.out.println("*****************************");
        // E remove(int index) 删除该列表中指定位置的元素
        System.out.println(list.remove(3)); //  111

        System.out.println("*****************************");
        // void addFirst(E e) 在该列表开头插入指定的元素
        list.addFirst("111");
        System.out.println(list); //  [111, aaa, ddd, ccc, aaa, eee]

        // void addLast(E e) 将指定的元素追加到此列表的末尾。
        list.addLast("666");
        System.out.println(list); // [111, aaa, ddd, ccc, aaa, eee, 666]

        // E getFirst() 返回此列表中的第一个元素
        System.out.println(list.getFirst()); // 111

        // E getLast() 返回此列表中的最后一个元素。
        System.out.println(list.getLast()); // 666

        System.out.println("*****************************");
        // void push(E e) 将元素推送到由此列表表示的堆栈上
        list.push("888");
        System.out.println(list); //  [888, 111, aaa, ddd, ccc, aaa, eee, 666]

        // E pop() 从此列表表示的堆栈中弹出一个元素
        String pop = list.pop();
        System.out.println(pop); // 888

        System.out.println("****************************");

        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

        System.out.println("****************************");
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }
}

测试结果:

6
[aaa, ddd, ccc, 111, aaa, eee]
aaa
eee
*****************************
111
*****************************
[111, aaa, ddd, ccc, aaa, eee]
[111, aaa, ddd, ccc, aaa, eee, 666]
111
666
*****************************
[888, 111, aaa, ddd, ccc, aaa, eee, 666]
888
****************************
111
aaa
ddd
ccc
aaa
eee
666
****************************
111
aaa
ddd
ccc
aaa
eee
666

二、聊聊 ArrayList

1. ArrayList 的底层源码

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable

ArrayList 是从JDK1.2 引入的。

它是可调整大小的数组,实现了List接口。 实现所有可选列表操作,并允许所有元素包括null 。 除了实现List 接口之外,该类还提供了一些方法来操纵内部使用的存储列表的数组的大小。 (这个类是大致相当于Vector,不同之处在于它是不同步的)。

内部封装一个数组,用数组来存储数据。内部数组的默认初始容量 10,存满后 1.5 倍增长

从 JDK1.8开始, ArrayList 一开始创建一个长度为 0 的数组,当添加第一个元素时再创建一个始容量为 10 的 数组。

2. ArrayList 的构造方法

  • ArrayList() 构造一个初始容量为十的空列表。
  • ArrayList(Collection<? extends E> c) 构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。
  • ArrayList(int initialCapacity) 构造具有指定初始容量的空列表。

3. ArrayList 的常用方法

ArrayList 的方法和 LinkedList 相同,但它没有两端操作数据的方法

  • boolean add(E e) 将指定的元素追加到此列表的末尾
  • int size() 返回此列表中的元素个数
  • E get(int index) 返回此列表中指定位置的元素
  • E remove(int index) 删除该列表中指定位置的元素
  • boolean remove(Object o) 从列表中删除指定元素的第一个出现(如果存在)
  • boolean contains(Object o) 如果此列表包含指定的元素,则返回 true
  • boolean addAll(int index, Collection<? extends E> c) 将指定集合中的所有元素插入到此列表中,从指定的位置开始
    - void clear() 从列表中删除所有元素
  • for / iterator 集合遍历

测试代码:

public class ArrayListTest {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        // boolean add(E e) 将指定的元素追加到此列表的末尾
        list.add(111);
        list.add(666);
        list.add(333);
        list.add(888);
        list.add(111);
        list.add(999);
        // int size() 返回此列表中的元素个数
        System.out.println(list.size()); // 6
        System.out.println(list); // [111, 666, 333, 888, 111, 999]

        // E get(int index) 返回此列表中指定位置的元素
        System.out.println(list.get(3)); // 888

        // E remove(int index) 删除该列表中指定位置的元素。
        list.remove(3);
        System.out.println(list); // [111, 666, 333, 111, 999]

        // boolean remove(Object o) 从列表中删除指定元素的第一个出现(如果存在)
        System.out.println(list.remove(Integer.valueOf(111))); // true
        System.out.println(list); // [666, 333, 111, 999]

        System.out.println("******************************");
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

        // 用三种方式遍历集合
        System.out.println("******************************");
        Iterator<Integer> it = list.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }

        System.out.println("******************************");
        for (Integer integer : list) {
            System.out.println(integer);
        }

        System.out.println("******************************");
        // boolean contains(Object o) 如果此列表包含指定的元素,则返回 true
        boolean contains = list.contains(666);
        System.out.println(contains); // true

        System.out.println("******************************");
        ArrayList<Integer> list1 = new ArrayList<Integer>();
        list1.add(123);
        list1.add(456);
        //  boolean addAll(int index, Collection<? extends E> c)
        //  将指定集合中的所有元素插入到此列表中,从指定的位置开始。
        list.addAll(1, list1);
        System.out.println(list); // [666, 123, 456, 333, 111, 999]
        System.out.println(list1); // [123, 456]

        // void clear() 从列表中删除所有元素
        list1.clear();
        System.out.println(list1); // []
    }
}

测试结果:

6
[111, 666, 333, 888, 111, 999]
888
[111, 666, 333, 111, 999]
true
[666, 333, 111, 999]
******************************
666
333
111
999
******************************
666
333
111
999
******************************
666
333
111
999
******************************
true
******************************
[666, 123, 456, 333, 111, 999]
[123, 456]
[]

三、两者与 Vector 的区别

1.ArrayList 和 LinkedList 的区别

二者都线程不安全,但是效率比 Vector 的高

  • ArrayList 底层是以 数组 的形式保存数据,随机访问集合中的元素比LinkedList 快(原因是 LinkedList 要移动指针);
  • LinkedList 内部以 链表 的形式保存集合里面数据,它随机访问集合中的元素性能比较慢,但是新增和删除时速度比 ArrayList 快(原因是 ArrayList 要移动数据)。

2.ArrayList 和 Vector 的区别

  • ArrayList 和 Vector 底层都是 数组
  • ArrayList 每次扩容的情况下扩容为原来的1.5 倍。线程不安全,当多个线程同时访问同一个ArrayList 集合时,如果两个或两个以上的线程修改了 ArrayList 集合,则必须手动保证该集合的同步性。
  • Vector 是同步类,其线程安全,但是它的访问比较慢。Vector 每次扩容为其空间大小的 2 倍。
  • 15
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
### 回答1: 非常感谢您的问题。我可以回答您的第一个问题,这是一个关于编程语言的问题。 ArrayListLinkedList都是Java编程语言中的集合框架(Collection Framework)中的两种不同的数据结构。 ArrayList是一种基于数组实现的动态数组,它可以根据需要自动增长和缩小。当元素添加到ArrayList中时,它们存储在连续的内存块中。因此,当需要随机访问列表中的元素时,ArrayListLinkedList更快,因为它支持常数时间的随机访问(即O(1)时间复杂度)。 LinkedList是一种基于链表实现的数据结构,每个元素都包含指向下一个元素的指针。当元素添加到LinkedList中时,它们存储在内存中的任意位置。因此,当需要在列表中添加或删除元素时,LinkedListArrayList更快,因为它支持常数时间的添加和删除操作(即O(1)时间复杂度)。 因此,ArrayListLinkedList都有其各自的优缺点,具体使用哪一个取决于需要实现的操作。如果需要进行频繁的随机访问,那么ArrayList是更好的选择。如果需要进行频繁的插入和删除操作,那么LinkedList是更好的选择。 希望这能够回答您的问题。如果您有任何其他问题,请随时问我。 ### 回答2: ArrayListLinkedList是Java中两种常用的集合类实现,它们主要在内部数据结构和操作方式上有所不同。 1. 内部数据结构: - ArrayList是基于数组实现的动态数组,它内部维护了一个Object类型的数组来存储元素。当数组容量不足时,ArrayList会进行扩容。 - LinkedList则是基于双向链表实现的,它的每个节点都持有前后节点的引用。 2. 插入和删除操作: - ArrayList在中间或开头插入/删除元素时,需要将插入/删除位置之后的元素向后或前移动,因为数组是连续存储的。 - LinkedList在中间或开头插入/删除元素时,只需要更新前后节点的引用即可,不需要像ArrayList一样进行移动元素。 3. 随机访问: - ArrayList支持随机访问,可以通过索引直接访问元素,时间复杂度为O(1)。 - LinkedList不支持随机访问,需要通过遍历链表来定位元素,时间复杂度为O(n)。 4. 内存占用: - ArrayList需要额外的空间来存储未使用的预留容量。 - LinkedList需要额外的空间来存储前后节点的引用。 综上所述,ArrayList适用于随机访问和频繁修改的场景,而LinkedList适用于频繁插入和删除元素的场景。在选择使用时,还需要考虑到具体的操作需求和性能要求。 ### 回答3: ArrayListLinkedList是Java中常用的两种集合类,它们都实现了List接口,但在内部实现和性能方面有一些区别。 首先,ArrayList是基于动态数组的数据结构,它可以根据需要自动调整容量。而LinkedList是基于双向链表的数据结构,它由一个个节点组成,每个节点包含了元素本身及其前后两个节点的引用。 其次,对于随机访问元素(例如通过索引访问List中的元素),ArrayList的性能更优。由于ArrayList内部使用数组实现,通过索引可以直接访问到指定位置的元素,时间复杂度为O(1)。而LinkedList需要从头节点或尾节点开始遍历链表,直到找到目标位置,时间复杂度为O(n)。 另外,对于频繁的插入或删除操作,LinkedList的性能更好。由于LinkedList底层是基于链表结构,插入或删除元素只需要改变节点的引用,时间复杂度为O(1)。而ArrayList在插入或删除元素时,需要移动其他元素的位置,时间复杂度为O(n)。 此外,LinkedList还提供了一些ArrayList没有的特殊操作,如可以在链表的头部或尾部进行快速插入或删除操作。 综上所述,ArrayListLinkedList在不同场景下有不同的优势,ArrayList适合随机访问元素,而LinkedList适合频繁的插入或删除操作。选择使用哪种集合类应根据具体的需求情况来确定。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值