Java集合框架(四)List接口

List是一个有序(插入顺序)的Collection(有时候也叫做序列)。可以包含重复的元素。除了从Collection继承过来的方法外,还包含下面的操作:

  • 位置访问:基于元素位置索引来操作元素。比如getsetaddaddAllremove
  • 搜索:从List中搜索指定的元素,并且返回其位置索引。如indexOflastIndexOf
  • 迭代:扩展Iterator提供利用List序列特性的遍历操作。listIterator方法返回此类迭代器
  • 区间视图:sublist方法提供任意的区间操作。
    Java平台提供了两种通用的List实现:ArrayListLinkedList

集合相关操作

继承自Collection的相关集合操作,基本都符合你期望的样子。如果对这些不熟悉的话,请查看Collection接口。
需要提到的是,remove操作将会移除List中第一个出现的指定元素,addaddAll操作总是会将新的元素添加到原有List末尾。因此,下面的方法可以将一个List添加到另一个List后面。
list1.addAll(list2);
上面这种方式将会改变list1,可以通过下面的方式创建一个新的List来包含list1list2
List list3 = new ArrayList(list1);
list3.addAll(list2);

位置访问和搜索操作

基本的位置访问操作是getsetaddremovesetremove操作在元素被覆盖和删除之前会先返回旧的元素。别的操作(indexOf和lastIndexOf)将会返回从List中找到的第一个或者最后一个元素的索引。
addAll操作将指定的Collection中的所有元素,按照Collection的迭代顺序插入到指定位置。此操作是Collection中的addAll的基于位置访问版本。
下面是一个小方法用来交换List的两个不同位置的元素。
public static void swap(List list, int i, int j) {
E tmp = list.get(i);
list.set(i, list.get(j));
list.set(j, tmp);
}
当然,这是一个多态算法:它可用来交换任意List的两个元素,而忽略了List的实现类型。下面是另外一个多态算法,使用了前面的swap方法:
public static void shuffle(List list, Random rnd) {
for (int i = list.size(); i > 1; i--) {
swap(list, i - 1, rnd.nextInt(i));
}
}
这个算法包含在Collections中,用来随机打乱List。实际上,如果List的实现类型是LinkedList,此算法的平均运行时间复杂度将会是O(n2)。因为链表基于位置的查找效率不高,为O(n)。在Collections类中,shuffle方法的实现如下:

Java集合框架(四)List接口_第1张图片
Collections中的shuffle方法

注意到, shuffle方法会先去判断 List是否实现了 RandomAccess类型,而 RandomAccess实际上是一个空接口(不定义任何方法),基于名字也可以看出,它用来标记子类实现是否为随机访问。在Java类库中,List的实现者 ArrayList类实现了此接口,而 LinkedList没有实现此接口。因此,从这里也可以看出,由于链表并非随机访问类型,其直接使用基于位置的混淆效率将会低下。针对这种并非随机访问的 List,则先生成其数组形式的引用拷贝,对数组进行位置混淆后,再将打乱的数组写回 List
注意不同的 List实现可能会影响到算法效率时,可以根据判断 List是否实现了 RandomAccess接口来区分是否可随机访问这种技巧。

迭代器

Listiterator方法返回Iterator类型的迭代器。同时,还提供给一个增强版ListIterator,由listIterator返回。ListIterator可以让你从两个方向遍历List,在迭代过程中修改列表,并且获取当前遍历的位置。
ListIterator继承自Iterator接口,继承的三个方法(hasNextnextremove)和Iterator接口的方法做完全一样的事情。另外还包含了hasPreviousprevious方法,用来从后向前遍历。从方法名可以看出,其是和hasNextnext方法相对应的。
下面是一个标准的从后向前遍历List的方法:

for (ListIterator it = list.listIterator(list.size()); it.hasPrevious(); ) {
     Type t = it.previous();
      ……
}

注意到listIterator方法有两种形式。无参数的形式返回一个位置位于List开始处的ListIterator,带一个int参数的返回一个位于指定位置索引(index)的ListIterator。这里的位置索引(index)指向被首次next调用将会返回的元素。而index-1指向被首次previous调用的元素。在一个长度为nList中,indexn+1个有效的值:从0到n。
直观地说,光标位置总是位于两个元素之间——一个由调用previous返回的元素和一个由调用next返回的元素。这n+1个有效index对应于n个元素之间的n+1个间隙。下图展示了一个包含四个元素的List可以有五个可能的光标位置:

Java集合框架(四)List接口_第2张图片
五个可能的光标位置

区间视图操作

区间视图操作subList(int fromIndex, int toIndex)返回一个原有List的部分List视图,索引包括fromIndex,不包括toIndex
注意:这个子List并非原有List的拷贝,实际上其为同一List,只不过只给你看你想要的那部分。作用在原有List上的操作将会影响到新的子List。如果修改了原有List,可能导致子List紊乱。同样对子List进行添加和删除将会影响到原有List
任何只需要考虑List一部分的范围操作,都可以考虑用subList来进行替代。比如,下面可以用来删除List的一部分元素:

list.subList(fromIndex, toIndex).clear();
List算法

Collections类中的大部分算法都适用于List,下面是这些算法的一个总结:

  • sort——使用归并排序算法来对List进行排序
  • shuffle——随机打乱List中的元素
  • reverse——对List进行逆序操作
  • rotate——以一个给定的距离旋转List中的所有元素
  • swap—— 交换List中指定位置的元素
  • replaceAll——将在List中所有出现的指定值替换为新的值
  • fill ——用指定值覆盖List中所有元素
  • copy——拷贝源List到墓道目的List
  • binarySearch——使用二分查找算法在一个排好序的List中查找给定的元素
  • indexOfSubList——返回List等于给定子List的第一个出现位置索引
    _ lastIndexOfSubList——返回List中等于给定子List的最后一个出现位置索引

以上文章参考:
http://docs.oracle.com/javase/tutorial/collections/interfaces/list.html

你可能感兴趣的:(Java集合框架(四)List接口)