五、Java集合类(一)List

本文主要介绍了Java中的List接口及其常见的实现类ArrayList、LinkedList和Vector。ArrayList基于动态数组,适合快速查询,但插入删除较慢;LinkedList采用双向链表,插入删除高效但查询慢;Vector是线程安全的ArrayList,但效率较低。此外,还提及了Stack,它是Vector的子类,实现栈的数据结构。在选择使用时,应根据是否需要线程安全及操作频率来决定使用哪种实现类。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天的博客主题

      基础篇 --》常用类 --》Java集合类(一)List


上一篇讲解了最顶级的集合类Conllection。

说是集合类不要认为是一个类,只不过是一个总称而已,他其实是一个接口,别混淆了。

List

public interface List<E> extends Collection<E> {}

List也是一个接口,继承了Conllection。是Conllection的一个子接口。

List接口大概的一个结构体系是这样子的

 

通过源码注释所得: list是一个有序,可重复的集合。

LIst只是一个接口,都是需要子类来实现的,没什么好讲的。具体看子类实现吧

 

AbstractList

 

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {}

Collection集合里的一个抽象类,继承了AbstractCollection抽象类,实现类List接口。

是List接口的一个子类。ArrayList的父类。

虽然是个抽象类,但却只有一个抽象方法。

平时根本用不到,只是内部使用的一个类。等以后有时间出文章通过源码去分析这个类的作用。

 

ArrayList

 

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

ArrayList继承了AbstractList类,实现了List、RandomAccess、Cloneable、和序列化接口。

ArrayList是List接口的一个实现类。

ArrayList是我们使用最多的一个List集合。

底层数据结构是一个数组队列,相当于动态数组。

特点:

  • 容量不固定。(有最大值就是int最大值减8)
  • 按照插入顺序来保存元素,可以利用下标来查找值。
  • 按照下标访问元素最快。
  • 支持元素可以为null。
  • 占用空间小。(对比 LinkedList,不占用额外空间来维护链表结构)
  • 可以随机访问。

缺点:

  • 线程不安全。
  • 在中间插入元素慢。
  • 删除元素慢。

核心方法(常用API)

 

public static void main(String[] args) {
    // ===核心方法 add(), addAll()

    // 声明一个空的集合
    List list = new ArrayList();

    // 往集合添加一个元素
    list.add(0);

    // 往集合指定位置添加一个元素
    list.add(0,1);
    System.out.println(list);  // [1, 0]

    List list1 = new ArrayList();
    list1.add("2");
    // 往集合里添加一个集合
    list.addAll(list1);
    System.out.println(list);  // [1, 0, 2]

    List list2 = new ArrayList();
    list2.add("3");
    // 往集合指定位置添加一个集合
    list.addAll(0,list2);
    System.out.println(list);  // [3, 1, 0, 2]

    // 这里注意一下,当指定了集合的泛型之后,只能同类型对象的集合使用addAll(),否则在编译时期就会报错
    List<String> listStr = new ArrayList();
    ArrayList<String> listStr1 = new ArrayList();
    List<Integer> listInt = new ArrayList();
    ArrayList<Integer> listInt1 = new ArrayList();

    listStr.addAll(listInt);  // ×
    listStr.addAll(listStr1);  // √

    // ===核心方法 size()
      // 获取集合的长度
      int size = list.size();
    System.out.println(size);  // 4

    // ===核心方法 isEmpty()
    // 判断集合是否为空
    boolean empty = list.isEmpty();
    System.out.println(empty);  // false
    List list3 = new ArrayList();
    boolean empty1 = list3.isEmpty();
    System.out.println(empty1);  // true

    // ===核心方法 contains()
    // 判断集合是否包含某个元素(对数据类型有要求)
    boolean contains = list.contains(0);
    System.out.println(contains); // false
    boolean contains1 = list.contains("0");
    System.out.println(contains1); // true

    // ===核心方法 get()
    // 获取指定位置的元素
    Object o = list.get(0);
    System.out.println(o.toString());  // 3

    // ===核心方法 remove()  removeAll()  retainAll()
    // 移除指定位置的元素
    list.remove(3);
    System.out.println(list);	// [3, 1, 0]
    // 移除指定的元素
    list.remove("3");
    System.out.println(list);  // [1, 0]
    list.add(2);
    list.add(3);
    list.add(4);
    list.add(5);
    System.out.println(list);

    List list4 = new ArrayList(); // [1, 0, 2, 3, 4, 5]
    list4.add(3);
    list4.add(5);
    // 移除指定集合里的所有元素
    list.removeAll(list4);
    System.out.println(list); // [1, 0, 2, 4] 

    List list5 = new ArrayList();
    list5.add(1);
    list5.add(2);
    // 移除集合里除了指定集合外的所有元素
    list.retainAll(list5);
    System.out.println(list);	// [1, 2]

    // ===核心方法 subList()
    list.add(3);
    list.add(2);
    list.add(5);
    list.add(4);
    System.out.println(list);   // [1, 2, 3, 2, 5, 4]
    // 截取集合里指定位置的元素
    List list6 = list.subList(2, 4);
    System.out.println(list6); // [3, 2]

    // === 核心方法 sort()   这个方法用的比较少,没这样写过。
    list.sort(new Comparator<Integer>() {
        @Override
   	public int compare(Integer o1, Integer o2) {
            int i = o1 > o2 ? 1 : -1;
            return i;
   	}
    });
    System.out.println(list);  // [1, 2, 2, 3, 4, 5]
    // 替代方法。一般对集合排序都会用父类的这个排序算法
    Collections.sort(list);
    System.out.println(list);  // [1, 2, 2, 3, 4, 5]

    // ===核心方法 clear()
    // 清空集合里的所有元素
    list.clear();
    System.out.println(list);  // []
}

LinkedList

 

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

LinkedList继承了AbstractSequentialList类。实现了List、Deque、Cloneable和Serializable接口。

LinkedList也是List接口的一个实现类。

LinkedList底层数据结构是通过双向链表去实现的。

特点:

  • 容量大,因为是链表,不会出现容量不足的问题
  • 可以作为栈、队列、双端队列数据结构使用。
  • 在插入和删除元素是效率高。

缺点:

  • 同样线程是不安全的。
  • 随机访问速度慢。

核心方法(常用API)

 

public static void main(String[] args) {
    // 声明一个LinkedList集合
    LinkedList list = new LinkedList();
    // ===添加方法
    // 往集合内添加一个元素。在链表后添加一个元素
    list.add("1");
    System.out.println(list); // [1]
    // 往集合前头添加一个元素。在链表的最前增加一个元素
    list.addFirst("2");
    System.out.println(list); // [2, 1]
    // 往集合尾部添加一个元素。在链表的最后增加一个元素
    list.addLast("3");
    System.out.println(list); // [2, 1, 3]
    // 往集合指定位置添加一个元素
    list.add(2,"4");
    System.out.println(list); // [2, 1, 4, 3]
    // 和addFirst方法一样
    list.push("5");
    System.out.println(list); // [5, 2, 1, 4, 3]
    // 和addLast方法一样
    list.offer("6");
    System.out.println(list); // [5, 2, 1, 4, 3, 6]
    // JDK1.6版本之后才有的方法。和addFirst方法一样
    list.offerFirst("7");
    System.out.println(list); // [7, 5, 2, 1, 4, 3, 6]
    // JDK1.6版本之后才有的方法。和addLast方法一样
    list.offerLast("8");
    System.out.println(list); // [7, 5, 2, 1, 4, 3, 6, 8]

    // ===删除方法
    // 删除链表里的第一个元素
    list.remove();
    System.out.println(list); // [5, 2, 1, 4, 3, 6, 8]
    // 删除链表指定位置的元素
    list.remove(3);
    System.out.println(list); // [5, 2, 1, 3, 6, 8]
    // 删除链表指定的元素
    list.remove("8");
    System.out.println(list); // [5, 2, 1, 3, 6]
    // 删除链表头部元素,并返回
    list.removeFirst();
    System.out.println(list); // [2, 1, 3, 6]
    // 删除链表尾部元素,并返回
    list.removeLast();
    System.out.println(list); // [2, 1, 3]
    // 查询并删除链表第一个元素
    list.poll();
    System.out.println(list); // [1, 3]
    // 和removeFirst方法一样
    list.pop();
    System.out.println(list); // [3]

    list.add("2");
    list.add("1");
    list.add("4");
    list.add("5");
    list.add("6");
    System.out.println(list); // [3, 2, 1, 4, 5, 6]

    // === 查询方法
    // 获取指定位置的元素
    Object o = list.get(3);
    System.out.println(o);  // 4
    // 获取链表第一个元素
    Object first = list.getFirst();
    System.out.println(first); // 3
    // 获取链表最后一个元素
    Object last = list.getLast();
    System.out.println(last); // 6
    // 获取链表第一个元素,但不删除
    Object peek = list.peek();
    System.out.println(peek); // 3
    // 和peek方法一样
    Object peekFirst = list.peekFirst();
    System.out.println(peekFirst); // 3
    // 获取链表最后一个元素,但不删除
    Object peekLast = list.peekLast();
    System.out.println(peekLast); // 6
    // 获取链表长度
    int size = list.size();
    System.out.println(size); // 6
}

Vector(矢量队列)

 

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

继承了AbstractList抽象类,实现了List、RandomAccess、Cloneable和Serializable接口

我们发现Vector实现类的体系结构和ArrayList是一样的。

Vector类实现了一个动态数组。和 ArrayList 很相似,

但不同的是:Vector是同步访问的也就是说线程是安全的。Vector里面包含了许多传统方法,不属于集合里

特点:

  • 和ArrayList底层数据结构一样并且类实现也一样,其优点也一样 随机访问速度快,插入和移除性能较差 (这是数组的特点)
  • 重要一点就是线程安全

缺点:

  • 线程安全了,效率自然而然就低了

核心方法(常用API)

public static void main(String[] args) {
    
    // 声明一个Vector(矢量队列)集合
    Vector vector = new Vector();

    // 将指定的元素追加到此向量的末尾
    vector.add("1");
    vector.add("2");
    System.out.println(vector); // [1, 2]

    // 在此向量的指定位置增加指定的元素
    vector.add(1,"3");
    System.out.println(vector);

    // 将指定的集合添加到此向量的末尾
    List list = new ArrayList();
    list.add("4");
    vector.addAll(list);
    System.out.println(vector); // [1, 3, 2, 4]

    // 在此向量的指定位置增加指定的集合
    List list1 = new ArrayList();
    list1.add("5");
    vector.addAll(0,list1);
    System.out.println(vector); // [5, 1, 3, 2, 4]

    // 获取此向量的长度
    int size = vector.size();
    System.out.println(size); // 5

    // 返回此向量的当前容量,一般用不到
    int capacity = vector.capacity();
    System.out.println(capacity); // 10

    // 获取此向量指定位置的元素
    Object o = vector.get(3);
    System.out.println(o); // 2

    // 移除此向量里指定的元素
    vector.remove("5");
    System.out.println(vector); // [1, 3, 2, 4]

    // 移除此向量指定位置的元素
    vector.remove(2);
    System.out.println(vector); // [1, 3, 4]

    // 移除此向量里指定集合里的元素
    List list2 = new ArrayList();
    list2.add("3");
    vector.removeAll(list2);
    System.out.println(vector); // [1, 4]

    // 判断此向量是不是空的
    boolean empty = vector.isEmpty();
    System.out.println(empty); // false

    // 判断此向量是否包含指定的元素
    boolean contains = vector.contains("1");
    System.out.println(contains); // true

    // 此向量是否包含指定元素,包含返回对应下标,不包含返回-1
    int i = vector.indexOf("1");
    int i2 = vector.indexOf("11");
    System.out.println(i); // 0
    System.out.println(i2); // -1

    // 清空此向量里的所有元素
    vector.clear();
    System.out.println(vector); // []
}

 


Stack

 

public class Stack<E> extends Vector<E> {}

Stack继承了Vector,是Vector的子类。

Stack比较简单,继承了Vector。

Stack翻译过来是栈的意思,特性就是:先进后出(FILO Frist In Last Out)

特点就不用说了吧,是Vector的子类,那么父类有啥子类都会有啥的。

而Stack里面的方法也不是很多,除了一个构造函数之外只有5个方法。

public static void main(String[] args) {

    // 声明一个Stack(栈)集合
    Stack stack = new Stack();

    // 将指定元素推送到栈顶部
    stack.push("1");
    stack.push("2");
    stack.push("3");
    System.out.println(stack); // [1, 2, 3]

    // 获取栈顶部元素,但不会移除这个元素
    Object peek = stack.peek();
    System.out.println(peek); // 3

    // 移除栈顶部元素,并返回这个被移除的元素
    Object pop = stack.pop();
    System.out.println(pop); // 3

    System.out.println(stack); // [1, 2]

    // 栈是否为空
    boolean empty = stack.empty();
    System.out.println(empty); // false

    // 获取指定元素出现在栈上的位置
    int search = stack.search("2");
    System.out.println(search); // 1
}

总结

List是一个接口,继承Collection接口,是一个有序可重复的集合。

AbstractList是一个抽象类,继承AbstractCollection,实现List接口。

AbstractSequentialList是一个抽象类,继承AbstractList。

ArrayList底层数据结构实现是数组队列,相当于动态数组。由于是数组实现,所以随机访问效率高,插入/删除效率低。是List接口的一个实现类

LinkedList底层数据结构是双向链表。它也可以被当作堆栈、队列或双端队列进行操作。因为是链表实现,所以随机访问效率低,插入/删除效率高。

Vector是矢量队列,底层数据结构也是数组,和ArrayList一样。但ArrayList线程是不安全的,而Vector线程是安全的。

Stack是栈,继承Vector。它的特性就是:先进后出(FILO)

简单总结

  1. ArrayList底层数据结构是数组,查询快,增删慢。线程不安全,效率高。(比较常用)
  2. LinkedList底层数据结构式链表,查询慢,增删快。线程不安全,效率高。
  3. Vector底层数据结构是数组,查询快,增删慢。线程安全,效率低。

场景

学习的东西始终都是要来应用的,如果不用学了岂不是白学了。

那学完这篇集合之后,在Java当中我们在那些地方应用它呢?这么多实现类用的时候怎么选择呢?

再用的时候我们需要根据需求来抉择,

需要安全吗?如果要安全那就选择Vector(但是即使要用这个还是不要选择,后面分析)

查询的多就用ArrayList,增删多就用LinkedList。

一般在开发中信手捏来的就是ArrayList,还是这个比较用的多一点。

这些就是List集合里面一些常用的。我们先熟悉认识这些,等后边源码篇的时候会着重分析集合这些,这部分还是比较重要的。


 

坚持!!!

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值