0
点赞
收藏
分享

微信扫一扫

Java中的List集合,ArrayList与LinkList的优缺点等比较


使用List:

在集合类中,​​List​​是最基础的一种集合:它是一种有序列表。

​List​​​的行为和数组几乎完全相同:​​List​​​内部按照放入元素的先后顺序存放,每个元素都可以通过索引确定自己的位置,​​List​​的索引和数组一样,从0开始。

List的删除和添加操作,都非常的不方便,因为需要移动的元素太多了,比较费时间!

​​ArrayList​​:

因此,在实际应用中,需要增删元素的有序列表,我们使用最多的是​​ArrayList​​。实际上,​​ArrayList​​在内部使用了数组来存储所有元素。例如,一个​​ArrayList​​拥有5个元素,实际数组大小为6(即有一个空位)

Java中的List集合,ArrayList与LinkList的优缺点等比较_arraylist

当添加一个元素并指定索引到ArrayList时,ArrayList自动移动需要移动的元素:

Java中的List集合,ArrayList与LinkList的优缺点等比较_数组_02

然后,往内部指定索引的数组位置添加一个元素,然后把size加1:

Java中的List集合,ArrayList与LinkList的优缺点等比较_arraylist_03

继续添加元素,但是数组已满,没有空闲位置的时候,ArrayList先创建一个更大的新数组,然后把旧数组的所有元素复制到新数组,紧接着用新数组取代旧数组:

Java中的List集合,ArrayList与LinkList的优缺点等比较_数组_04

现在,新数组就有了空位,可以继续添加一个元素到数组末尾,同时size加1:

Java中的List集合,ArrayList与LinkList的优缺点等比较_集合类_05

可见,​​ArrayList​​把添加和删除的操作封装起来,让我们操作List类似于操作数组,却不用关心内部元素如何移动。

我们考察​​List<E>​​接口,可以看到几个主要的接口方法:


  • 在末尾添加一个元素:​​boolean add(E e)​
  • 在指定索引添加一个元素:​​boolean add(int index, E e)​
  • 删除指定索引的元素:​​int remove(int index)​
  • 删除某个元素:​​int remove(Object e)​
  • 获取指定索引的元素:​​E get(int index)​
  • 获取链表大小(包含元素的个数):​​int size()​

​​LinkList​​:

但是,实现List接口并非只能通过数组(即​​ArrayList​​的实现方式)来实现,另一种​​LinkedList​​通过“链表”也实现了List接口。在​​LinkedList​​中,它的内部每个元素都指向下一个元素:

Java中的List集合,ArrayList与LinkList的优缺点等比较_集合类_06

比较一下​​ArrayList​​和​​LinkedList​​:

Java中的List集合,ArrayList与LinkList的优缺点等比较_java_07

通常情况下,我们优先使用​​ArrayList​​。

使用List:

创建List

除了使用​​ArrayList​​和​​LinkedList​​,我们还可以通过List接口提供的​​of()​​方法,根据给定元素快速创建List:

List<Integer> list = List.of(1, 2, 5);

遍历List

和数组类型,我们要遍历一个List,完全可以用for循环根据索引配合get(int)方法遍历:

import java.util.List;//导入包
public class Main {
public static void main(String[] args) {
List<String> list = List.of("apple", "pear", "banana");
for (int i=0; i<list.size(); i++) {
String s = list.get(i);
System.out.println(s);
}
}
}

但这种方式并不推荐,一是代码复杂,二是因为​​get(int)​​方法只有​​ArrayList​​的实现是高效的,换成​​LinkedList​​后,索引越大,访问速度越慢。

所以我们要始终坚持使用迭代器​​Iterator​​​来访问​​List​​​。**​​Iterator​​​**本身也是一个对象,但它是由​​List​​​的实例调用​​iterator()​​​方法的时候创建的。​​Iterator​​​对象知道如何遍历一个​​List​​​,并且不同的​​List​​​类型,返回的​​Iterator​​对象实现也是不同的,但总是具有最高的访问效率。

​Iterator​​对象有两个方法:​​boolean hasNext()​​判断是否有下一个元素,​​E next()​​返回下一个元素。因此,使用Iterator遍历List代码如下:

import java.util.Iterator;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = List.of("apple", "pear", "banana");
for (Iterator<String> it = list.iterator(); it.hasNext(); ) {
String s = it.next();
System.out.println(s);
}
}
}

大家可能觉得Iterator()比较繁琐或者麻烦,但是我们要记住迭代器是最有效的方法!!!由于遍历比较常用,其实Java内部帮我们设计好了,使用的for each其实就是一个迭代器!

上面代码可以改为

import java.util.Iterator;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> list = List.of("apple", "pear", "banana");
for (String s : list) {
System.out.println(s);
}
}
}


实际上,只要实现了Iterable接口的集合类都可以直接用for each循环来遍历,Java编译器本身并不知道如何遍历集合对象,但它会自动把for each循环变成Iterator的调用,原因就在于Iterable接口定义了一个 Iteratoriterator()方法,强迫集合类必须返回一个Iterator实例




举报

相关推荐

0 条评论