五、Java集合类(一)List

    xiaoxiao2022-07-12  265

    今天的博客主题

          基础篇 --》常用类 --》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)

    简单总结

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

    场景

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

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

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

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

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

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

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


     

    坚持!!!

     

     

     

     

     

     

    最新回复(0)