Java 集合全教程—List

Java 集合全教程—List列表是一个有序的集合 有时称为序列

大家好,欢迎来到IT知识分享网。

Java 集合全教程—List


一、概述

列表是一个有序的集合(有时称为序列)。列表可能包含重复的元素。除了从Collection继承的操作外,List接口还包括以下操作:

  • 位置访问-根据元素在列表中的数字位置来操作元素。这包括get、set、add、addAll和remove等方法。
  • 搜索-在列表中搜索指定的对象并返回其数字位置。搜索方法包括indexOf和lastIndexOf。
  • 迭代-扩展了Iterator语义,以利用列表的顺序性。listIterator方法提供了这种行为。
  • 范围视图-子列表方法对列表执行任意范围操作。

Java平台包含两个通用的List实现。ArrayList通常是性能更好的实现,LinkedList在某些情况下提供更好的性能。

二、集合操作

从Collection继承的操作都按照您期望的方式进行,假设您已经熟悉它们。如果您不熟悉《收藏》中的它们,现在是阅读《收藏界面》部分的好时机。移除操作总是从列表中移除指定元素的第一个出现。add和addAll操作总是将新元素追加到列表的末尾。因此,下面的习语将一个列表连接到另一个列表。

list1.addAll(list2); 

这是这个习惯用法的一种非破坏性形式,它生成第三个列表,该列表由附加在第一个列表后面的第二个列表组成。

List<Type> list3 = new ArrayList<Type>(list1); list3.addAll(list2); 
List<String> list = people.stream() .map(Person::getName) .collect(Collectors.toList()); 

与Set接口一样,List加强了对equals和hashCode方法的要求,因此可以比较两个List对象的逻辑相等性,而不考虑它们的实现类。如果两个List对象以相同的顺序包含相同的元素,则它们是相等的。

三、操作接口和搜索操作

public static <E> void swap(List<E> a, int i, int j) { E tmp = a.get(i); a.set(i, a.get(j)); a.set(j, tmp); } 

当然,有一个很大的区别。这是一个多态算法:它交换任何List中的两个元素,而不管其实现类型如何。下面是另一个多态算法,它使用前面的交换方法:

public static void shuffle(List<?> list, Random rnd) { for (int i = list.size(); i > 1; i--) swap(list, i - 1, rnd.nextInt(i)); } 

该算法包含在Java平台的Collections类中,它使用指定的随机性源随机排列指定的列表。这有点微妙:它从底部向上运行列表,重复地将随机选择的元素交换到当前位置。与大多数天真的洗牌尝试不同,它是公平的(假设随机性来源不带偏见,所有排列的可能性都相等)和快速的(需要恰好list.size()-1交换)。以下程序使用此算法以随机顺序打印参数列表中的单词。

import java.util.*; public class Shuffle { public static void main(String[] args) { List<String> list = new ArrayList<String>(); for (String a : args) list.add(a); Collections.shuffle(list, new Random()); System.out.println(list); } } 

事实上,这个程序可以做得更短更快。Arrays类有一个名为asList的静态工厂方法,它允许将数组视为List。此方法不复制数组。列表中的更改会写入到数组中,反之亦然。生成的List不是通用List实现,因为它没有实现(可选)添加和删除操作:数组的大小不可调整。利用Arrays.asList并调用shuffle的库版本(使用默认的随机性源),您可以得到以下小程序,其行为与前一个程序相同:

import java.util.*; public class Shuffle { public static void main(String[] args) { List<String> list = Arrays.asList(args); Collections.shuffle(list); System.out.println(list); } } 

四、Iterators

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

Java 集合全教程—List

public int indexOf(E e) { for (ListIterator<E> it = listIterator(); it.hasNext(); ) if (e == null ? it.next() == null : e.equals(it.next())) return it.previousIndex(); // Element not found return -1; } 
public static <E> void replace(List<E> list, E val, E newVal) { for (ListIterator<E> it = list.listIterator(); it.hasNext(); ) if (val == null ? it.next() == null : val.equals(it.next())) it.set(newVal); } 
 public static <E> void replace(List<E> list, E val, List<? extends E> newVals) { for (ListIterator<E> it = list.listIterator(); it.hasNext(); ){ if (val == null ? it.next() == null : val.equals(it.next())) { it.remove(); for (E e : newVals) it.add(e); } } } 

五、Range-View操作

Range-View操作subList(int fromIndex,int to Index)返回此列表中索引范围从fromIndex(包含)到toIndex(排除)的部分的列表视图。这个半开放范围反映了典型的for循环。

for (int i = fromIndex; i < toIndex; i++) { ... } 
list.subList(fromIndex, toIndex).clear(); 

可以构造类似的习惯用法来搜索范围内的元素。

int i = list.subList(fromIndex, toIndex).indexOf(o); int j = list.subList(fromIndex, toIndex).lastIndexOf(o); 
 public static <E> List<E> dealHand(List<E> deck, int n) { int deckSize = deck.size(); List<E> handView = deck.subList(deckSize - n, deckSize); List<E> hand = new ArrayList<E>(handView); handView.clear(); return hand; } 
import java.util.*; public class Deal { public static void main(String[] args) { if (args.length < 2) { System.out.println("Usage: Deal hands cards"); return; } int numHands = Integer.parseInt(args[0]); int cardsPerHand = Integer.parseInt(args[1]); // Make a normal 52-card deck. String[] suit = new String[] { "spades", "hearts", "diamonds", "clubs" }; String[] rank = new String[] { "ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "jack", "queen", "king" }; List<String> deck = new ArrayList<String>(); for (int i = 0; i < suit.length; i++) for (int j = 0; j < rank.length; j++) deck.add(rank[j] + " of " + suit[i]); // Shuffle the deck. Collections.shuffle(deck); if (numHands * cardsPerHand > deck.size()) { System.out.println("Not enough cards."); return; } for (int i = 0; i < numHands; i++) System.out.println(dealHand(deck, cardsPerHand)); } public static <E> List<E> dealHand(List<E> deck, int n) { int deckSize = deck.size(); List<E> handView = deck.subList(deckSize - n, deckSize); List<E> hand = new ArrayList<E>(handView); handView.clear(); return hand; } } 

运行程序会产生如下输出:

% java Deal 4 5 [8 of hearts, jack of spades, 3 of spades, 4 of spades, king of diamonds] [4 of diamonds, ace of clubs, 6 of clubs, jack of hearts, queen of hearts] [7 of spades, 5 of spades, 2 of diamonds, queen of diamonds, 9 of clubs] [8 of spades, 6 of diamonds, ace of spades, 3 of hearts, ace of hearts] 

尽管subList操作非常强大,但在使用它时必须小心。如果以除返回的List之外的任何方式将元素添加到支持List或从支持List中删除元素,则subList返回的List的语义将变得未定义。因此,强烈建议您仅将subList返回的List用作临时对象,以便对支持List执行一个或一系列范围操作。使用子列表实例的时间越长,通过直接或通过另一个子列表对象修改支持列表来破坏它的可能性就越大。请注意,修改子列表的子列表并继续使用原始子列表是合法的(尽管不是同时使用)

六、List 算法

Collections类中的大多数多态算法都专门应用于List。有了所有这些算法,就可以很容易地操作列表。以下是这些算法的摘要,在“算法”部分将对其进行更详细的描述:

  • sort-使用合并排序算法对List进行排序,该算法提供了快速、稳定的排序。(稳定排序是指不重新排序相等元素的排序。)
  • shuffle-随机排列列表中的元素。
  • reverse-反转列表中元素的顺序。
  • rotate-将列表中的所有元素旋转指定的距离。
  • swap-交换列表中指定位置的元素。
  • replaceAll-用另一个指定值替换所有出现的值。
  • fill-用指定的值覆盖列表中的每个元素。
  • copy-将源列表复制到目标列表中。
  • binarySearch-使用二进制搜索算法在有序列表中搜索元素。
  • indexOfSubList-返回一个列表的第一个子列表与另一个列表相等的索引。
  • lastIndexOfSubList-返回一个列表的最后一个子列表的索引,该子列表等于另一个列表。

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/119641.html

(0)
上一篇 2025-11-04 07:33
下一篇 2025-11-04 08:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信