能懂系列之 List 集合详解

Java
240
0
0
2023-09-12



今天咱们来谈一谈 Java 的 list 集合吧,进入正题之前呢,咱们聊点题外话吧。前几天在工作中使用到了 map 的嵌套,也就是一个 map 的 value 是另一个 map, 这个由于是第一次接触呢,所以当时这个逻辑还是比较混乱的,因为不知道如果改了外层的 map , 内层的 value 会不会随之改变,后来做了好几个实例才发现不会,因为外层 map 的 key 所对应的 value 值都是和 key 绑定的,所以其实和一般的 map 的逻辑是一样的,这个等我之后有空的话再详细讲一讲吧。

好了,言归正传吧,下面正式进去今天的主题 — List

那么,问题来了,什么是 list 呢,list 的特性和使用方法种种的又是什么呢,接下来就让我一点一点的来说吧。

List 是什么?

首先,咱们来说说什么是 List 吧!

集合类是 Java 数据结构的实现。Java 的集合类是 java.util 包中的重要内容,它允许以各种方式将元素分组,并定义了各种使这些元素更容易操作的方法。Java 集合类是 Java 将一些基本的和使用频率极高的基础类进行封装和增强后再以一个类的形式提供。集合类是可以往里面保存多个对象的类,存放的是对象,不同的集合类有不同的功能和特点,适合不同的场合,用以解决一些实际问题。

以上,是百度百科对于 List 集合的说明。通俗地讲 List 就是一个存放数据的容器,他根据你存储的顺序来给对应的 索引 值,而索引呢,也是你用来取出值的一个标识。

List 的继承结构

List 的继承结构

上面那张图没有过多的花里胡哨,可以让我们很清晰的看出集合的一个大概的继承体系,然而我们今天只看 Collection 下的 list 接口以及其实现类,因为我们今儿就是研究它来了。

特有功能

List 集合是一个元素有序(每个元素都有对应的顺序索引,第一个元素索引为 0)、且可重复的集合。

List 是 Collection 接口的子接口,故而拥有 Collection 的所有方法。除此之外呢,还有一些对索引操作的方法。

今天我们主要说的还是 List 的实现类,毕竟它很常用。

List 整体

从上图,可以让我们对于 List 的三个实现类有一个大概的了解.

分类

1、ArrayList

ArrayList 是一个数组队列,相当于 「动态数组」 。与 Java 中的数组相比,它的容量能动态增长。它继承于 AbstractList,实现了 List , RandomAccess (随机访问), Cloneable(克隆), java.io.Serializable (可 序列化 )这些接口.

ArrayList 继承了 AbstractList,实现了 List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能.

ArrayList 实现了 RandmoAccess 接口,即提供了随机访问功能。RandmoAccess 是 java 中用来被 List 实现,为 List 提供快速访问功能的。在 ArrayList 中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问.

ArrayList 实现了 Cloneable 接口,即覆盖了函数 clone (),能被克隆。ArrayList 实现 java.io.Serializable 接口,这意味着 ArrayList 支持序列化,能通过序列化去传输.

ArrayList 的底层数据结构因为是数组,故而查询快,增删慢,线程不安全,效率高,可以存储重复元素。下面来看看 ArrayList 常用的一些方法吧。

1.1、add 方法:

向集合中插入数据,集合的索引下标是从 0 开始.

1.2、插入数据

向指定位置插入数据,两个参数,一个是索引,一个是数据,插入后这个索引后面的数据向后顺延.

1.3、删除数据

删除集合中的数据,参数是数据对应的索引值.

1.4、返回索引值.

指定元素再 list 集合中的位置,返回索引值.

1.5、set

替换 List 中对应位置的值,两个参数分别是索引及新的数据,此操作的返回值是被替换的数据.

1.6、get

返回指定索引的数据

1.7、addAll

新增集合操作,两个参数:插入的位置索引,插入的集合

1.8、lastIndexOf

返回元素最后一次出现的位置索引

1.9、subList

截取指定位置的数据,两个参数:开始位置的索引,结束位置的索引

上面所有代码的运行结果如下图:

好了,相信讲完这些大家会对 ArrayList 的使用有了一些比较具体的了解了。

不过厚此薄彼不好,下面我们来说说 List 的另外两个实现类吧,不过主要就是说一下它们和 ArrayList 的一个区别及它们本身的优势吧.

2、LinkedList

LinkedList 可以看做为一个双向链表,所有的操作都可以认为是一个双向链表的操作,因为它实现了 Deque 接口和 List 接口。同样,LinkedList 也是线程不安全的,如果在并发环境下使用它,同样用 Colletions 类中的静态方法 synchronizedList () 对 LinkedList 进行调用即可. LinkedList 与 ArrayList 最大的区别是 LinkedList 更加灵活,并且部分方法的效率比 ArrayList 对应方法的效率要高很多,对于数据频繁出入的情况下,并且要求操作要足够灵活,建议使用 LinkedList;对于数组变动不大,主要是用来查询的情况下,可以使用 ArrayList。

LinkedList 常用方法:

  • toArray (): 以正确的顺序(从第一个到最后一个 )返回一个包含此列表中所有元素的数组
  • size (): 返回此列表中的元素数
  • set (int index,E element): 用指定的元素替换此列表中指定位置的元素
  • removeLast (): 从此列表中删除并返回最后一个元素
  • removeFirst (): 从此列表中删除并返回第一个元素
  • remove (int index): 删除该列表中指定位置的元素
  • getFirst (): 返回此列表中的第一个元素
  • getLast (): 返回此列表中的最后一个元素
  • get (int index): 返回此列表中指定位置的元素
  • add (E element): 将指定的元素追加到此列表的末尾
  • add (int index,E element): 在此列表中的指定位置插入指定的元素
  • addFirst (E element): 在该列表开头插入指定的元素
  • addLast (E element) : 将指定的元素追加到此列表的末尾
  • clear (): 从列表中删除所有元素

3、 Vector

Vector 也是一个类似于 ArrayList 的可变长度的数组类型,它的内部也是使用数组来存放数据对象的。值得注意的是 Vector 与 ArrayList 唯一的区别是,Vector 是 线程安全 的,即它的大部分方法都包含有关键字 synchronized. 因此,若对于单一线程的应用来说,最好使用 ArrayList 代替 Vector,因为这样效率会快很多(类似的情况有 StringBuffer 与 StringBuilder);而在多线程程序中,为了保证数据的同步和一致性,可以使用 Vector 代替 ArrayList 实现同样的功能. 「Vector 常用方法:」

  • add (E element): 将指定的元素追加到此 Vector 的末尾
  • add (int index,E element):在此 Vector 中的指定位置插入指定的元素
  • elementAt (int index): 返回指定索引处的组件
  • get (int index): 返回此向量中指定位置的元素
  • removeElementAt (int index): 删除指定索引处的组件
  • removeRange (int fromIndex,int toIndex):从此列表中删除所有索引为 fromIndex (含)和 toIndex 之间的元素

上面大体说了说 List 集合中另外两种实现类的一些基本详情,最后,既然是一系列的数据,那么必然会面临一个遍历的问题,所有本文的最后我们来看一看 List 的遍历方式 (其实只是 ArrayList 的遍历方式).

3.1、通过迭代器遍历。即通过 Iterator 去遍历.

 List<String> list = new ArrayList();
        list.add(new String("book"));
        list.add(new String("book"));
        list.add(new String("book "));
        String value = null;
        Iterator iter = list.iterator();
        while (iter.hasNext()) {
                value = (String)iter.next();
                System.out.println(value);
        }

结果展示:

3.2、随机访问 index, 通过索引值去遍历.

由于 ArrayList 实现了 RandomAccess 接口,它支持通过索引值去随机访问元素.

 List<String> list = new ArrayList();
        list.add(new String("book"));
        list.add(new String("book"));
        list.add(new String("book "));
        String value = null;
        int size = list.size();
        for (int i=; i<size; i++) {
                value = (String)list.get(i);
                System.out.println(value);
        }

结果展示:

3.3、增强 for (foreach) 循环遍历

 List<String> list = new ArrayList();
        list.add(new String("book"));
        list.add(new String("book"));
        list.add(new String("book"));
        String value = null;
        for (String books:list) {
                value = books;
                System.out.println(value);
        }

结果展示:

小结

List 中元素是有序的,元素可以重复,因为该集合体有索引

ArrayList:

  • 底层数据结构是数组,查询快,增删慢。
  • 线程不安全,效率高。
  • 当元素放满了后,默认以原长度的 50%+1 的长度加长集合容器的长度。

LinkedList:

  • 底层数据结构是链表,查询慢,增删快。
  • 线程不安全,效率高。
  • Vector (线程安全的) 相对 ArrayList 查询慢
  • Vector 相对 LinkedList 增删慢 (数组结构)

Vector:

  • 底层数据结构是数组,查询快,增删慢。
  • 线程安全,效率低。
  • 当元素放满了后,默认以原长度 100% 的长度加长集合容器的长度

好啦,今天的关于 list 集合的一些知识就讲解结束啦,有什么错误或不足欢迎大家留言指正,程序员的路上并肩前行吧。