在Java Collections Framework中,不同类型的集合使用不同类型的数据结构以不同的方式存储它们的元素。 集合框架提供了遍历集合的以下方法: 使用迭代器 使用for-each循环 使用forEach()方法 使用迭代器 迭代器可以对集合执行以下三个操作: 检查是否有尚未访问的元素。 hasNext() 检查是否有下一个访问的元素。 next() 删除集合的最后访问元素。 remove() 例子1 使用迭代器打印列表的所有元素: import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Main { public static void main(String[] args) { // Create a list of strings List<String> names = new ArrayList<>(); names.add("A"); names.add("B"); names.add("C"); Iterator<String> nameIterator = names.iterator(); while (nameIterator.hasNext()) { String name = nameIterator.next(); System.out.println(name); } } } 结果: A B C 例2 使用迭代器遍历列表的所有元素,并使用remove()方法删除该元素: import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Main { public static void main(String[] args) { // Create a list of strings List<String> names = new ArrayList<>(); names.add("A"); names.add("B"); names.add("C"); Iterator<String> nameIterator = names.iterator(); while (nameIterator.hasNext()) { String name = nameIterator.next(); System.out.println(name); nameIterator.remove(); } System.out.println(names); } } 结果: A B C [] 使用for-each循环 使用for-each循环遍历任何实现类实现Iterable接口的集合。 import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<String> names = new ArrayList<>(); names.add("A"); names.add("B"); names.add("C"); for (String name : names) { System.out.println(name); } } } 结果: A B C 使用forEach()方法 Iterable接口包含一个新的 forEach(Consumer action)方法,该方法遍历所有元素并应用操作。 import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { // Create a list of strings List<String> names = new ArrayList<>(); names.add("A"); names.add("B"); names.add("C"); names.forEach(System.out::println); } } 结果: A B C
Set 表示唯一对象的集合。集合中元素的排序是不相关的。 集合框架提供三种类型的集合: 数学集 排序集 导航集 数学集 Set 接口对数学中的一组进行建模。集合是唯一元素的集合。 Java最多允许一个Set中的一个空元素。 Set 中元素的排序并不重要。 Java不保证 Set 中元素的排序。 当循环遍历 Set 的所有元素时,你得到 Set 中的每个元素一次。 HashSet import java.util.HashSet; import java.util.Set; public class Main { public static void main(String[] args) { Set<String> s1 = new HashSet<>(); // Add a few elements s1.add("HTML"); s1.add("CSS"); s1.add("XML"); s1.add("XML"); // Duplicate // Create another set by copying s1 Set<String> s2 = new HashSet<>(s1); // Add a few more elements s2.add("Java"); s2.add("SQL"); s2.add(null); // one null is fine s2.add(null); // Duplicate System.out.println("s1: " + s1); System.out.println("s1.size(): " + s1.size()); System.out.println("s2: " + s2); System.out.println("s2.size(): " + s2.size()); } } 结果: s1: [HTML, CSS, XML] s1.size(): 3 s2: [null, SQL, HTML, CSS, XML, Java] s2.size(): 6 LinkedHashSet LinkedHashSet 在插入元素时保持元素顺序 import java.util.LinkedHashSet; import java.util.Set; public class Main { public static void main(String[] args) { Set<String> s1 = new LinkedHashSet<>(); s1.add("A"); s1.add("B"); s1.add("C"); s1.add("D"); System.out.println("LinkedHashSet: " + s1); } } 结果: LinkedHashSet: [A, B, C, D] 集合操作 我们可以对集合执行并集,交集和差分运算。 import java.util.HashSet; import java.util.Set; public class Main { public static void main(String[] args) { Set<String> s1 = new HashSet<>(); s1.add("HTML"); s1.add("CSS"); s1.add("XML"); Set<String> s2 = new HashSet<>(); s2.add("Java"); s2.add("Javascript"); s2.add("CSS"); System.out.println("s1: " + s1); System.out.println("s2: " + s2); performUnion(s1, s2); performIntersection(s1, s2); performDifference(s1, s2); } public static void performUnion(Set<String> s1, Set<String> s2) { Set<String> s1Unions2 = new HashSet<>(s1); s1Unions2.addAll(s2); System.out.println("s1 union s2: " + s1Unions2); } public static void performIntersection(Set<String> s1, Set<String> s2) { Set<String> s1Intersections2 = new HashSet<>(s1); s1Intersections2.retainAll(s2); System.out.println("s1 intersection s2: " + s1Intersections2); } public static void performDifference(Set<String> s1, Set<String> s2) { Set<String> s1Differences2 = new HashSet<>(s1); s1Differences2.removeAll(s2); Set<String> s2Differences1 = new HashSet<>(s2); s2Differences1.removeAll(s1); System.out.println("s1 difference s2: " + s1Differences2); System.out.println("s2 difference s1: " + s2Differences1); } } 结果: s1: [HTML, CSS, XML] s2: [Javascript, CSS, Java] s1 union s2: [Javascript, HTML, CSS, XML, Java] s1 intersection s2: [CSS] s1 difference s2: [HTML, XML] s2 difference s1: [Javascript, Java]
排序集是在其元素上有排序的集合。 SortedSet 接口表示Java集合中的排序集合框架。 排序集中的元素可以按照自然顺序排序可比较的接口或使用 Comparator 。 SortedSet 必须知道如何在添加元素时对其元素进行排序检查两个接口: 如果它的元素实现了Comparable接口,它将使用compareTo()方法来排序项目。 我们可以称之为自然顺序排序。 我们可以传递一个比较器做自定义排序。 如果指定了 Comparator ,则 Comparator 是用于排序并忽略 Comparable 接口。 TreeSet 类是Collection框架中SortedSet接口的一个实现。 例子: 添加 String 对象 SortedSet 。 String 类实现 Comparable 接口。 SortedSet将使用 Comparable 接口及其 compareTo()方法对String值进行排序。 import java.util.SortedSet; import java.util.TreeSet; public class Main { public static void main(String[] args) { SortedSet<String> sortedNames = new TreeSet<>(); sortedNames.add("Java"); sortedNames.add("SQL"); sortedNames.add("HTML"); sortedNames.add("CSS"); System.out.println(sortedNames); } } 结果: [CSS, HTML, Java, SQL] 例子: SortedSet 接口继承了 Set 接口的所有方法,并添加了一些方法来返回子集。 subSet(E fromElement,E toElement)方法从 SortedSet 返回fromElement(包含)和toElement(exclusive)之间的元素。 import java.util.SortedSet; import java.util.TreeSet; public class Main { public static void main(String[] args) { SortedSet<String> names = new TreeSet<>(); names.add("HTML"); names.add("Java"); names.add("SQL"); names.add("CSS"); System.out.println("Sorted Set: " + names); System.out.println("First: " + names.first()); System.out.println("Last: " + names.last()); SortedSet<String> ssBeforeCSS = names.headSet("CSS"); System.out.println(ssBeforeCSS); SortedSet<String> ssBetwenCSSAndHTML = names.subSet("CSS", "HTML"); System.out.println(ssBetwenCSSAndHTML); SortedSet<String> ssCSSAndAfter = names.tailSet("CSS"); System.out.println(ssCSSAndAfter); } } 结果: Sorted Set: [CSS, HTML, Java, SQL] First: CSS Last: SQL [] [CSS] [CSS, HTML, Java, SQL]
导航集是一个有序集,允许您使用其子集在各种方式。 NavigableSet 表示Java集合中的可导航集合框架。 NavigableSet 接口继承了SortedSet接口和扩展 SortedSet 。 NavigableSet 界面可以以相反的顺序导航集合与SortedSet中定义的顺序相比。 headSet(), tailSet()和 subSet()从 NavigableSet 接口接受布尔标志以将元素包括在子集边界的开始或结束处。 lower(),floor(),higher()和ceiling()从NavigableSet接口搜索基于搜索条件的元素。 lower()方法返回小于指定元素的最大元素。 floor()方法返回 NavigableSet 中小于或等于指定元素的最大元素。 higher()方法返回最小元素大于指定元素的 NavigableSet 。 ceiling()方法返回 NavigableSet 中大于或等于指定元素的最小元素。 pollFirst()和 pollLast()分别检索和删除 NavigableSet 的第一个和最后一个元素。 如果NavigableSet为空,它们返回null。 TreeSet 类是 NavigableSet 接口的实现类之一。我们可以使用 TreeSet 作为集合,排序集合和可导航集合。 import java.util.NavigableSet; import java.util.TreeSet; public class Main { public static void main(String[] args) { NavigableSet<Integer> ns = new TreeSet<>(); ns.add(0); ns.add(1); ns.add(2); ns.add(3); ns.add(4); ns.add(5); ns.add(6); // Get a reverse view of the navigable set NavigableSet<Integer> reverseNs = ns.descendingSet(); // Print the normal and reverse views System.out.println("Normal order: " + ns); System.out.println("Reverse order: " + reverseNs); NavigableSet<Integer> threeOrMore = ns.tailSet(3, true); System.out.println("3 or more: " + threeOrMore); System.out.println("lower(3): " + ns.lower(3)); System.out.println("floor(3): " + ns.floor(3)); System.out.println("higher(3): " + ns.higher(3)); System.out.println("ceiling(3): " + ns.ceiling(3)); System.out.println("pollFirst(): " + ns.pollFirst()); System.out.println("Navigable Set: " + ns); System.out.println("pollLast(): " + ns.pollLast()); System.out.println("Navigable Set: " + ns); System.out.println("pollFirst(): " + ns.pollFirst()); System.out.println("Navigable Set: " + ns); System.out.println("pollFirst(): " + ns.pollFirst()); System.out.println("Navigable Set: " + ns); System.out.println("pollFirst(): " + ns.pollFirst()); System.out.println("Navigable Set: " + ns); System.out.println("pollFirst(): " + ns.pollFirst()); System.out.println("pollLast(): " + ns.pollLast()); } } 结果: Normal order: [0, 1, 2, 3, 4, 5, 6] Reverse order: [6, 5, 4, 3, 2, 1, 0] 3 or more: [3, 4, 5, 6] lower(3): 2 floor(3): 3 higher(3): 4 ceiling(3): 3 pollFirst(): 0 Navigable Set: [1, 2, 3, 4, 5, 6] pollLast(): 6 Navigable Set: [1, 2, 3, 4, 5] pollFirst(): 1 Navigable Set: [2, 3, 4, 5] pollFirst(): 2 Navigable Set: [3, 4, 5] pollFirst(): 3 Navigable Set: [4, 5] pollFirst(): 4 pollLast(): 5
列表是对象的有序集合,在 List 界面中定义。 List 接口表示集合框架中的列表。 列表可以具有重复的元素。并且我们可以在列表中存储多个空值。 List 接口继承了集合接口和它添加了一些方法来支持使用索引访问其元素。 我们可以在 List 或的末尾添加一个元素在由整数索引标识的任何位置。 列表中元素的索引是从零开始的。 我们可以使用以下方法使用索引添加,获取,删除和替换其元素。 its add(int index, E element), addAll(int index, Collection<? extends E> c), get(int index), remove(int index) set(int index, E element) 我们可以搜索元素的位置 List 使用indexOf(Object o)或 lastIndexOf(Object o)方法。 indexOf()方法搜索指定的对象从开始,它返回索引的对象的第一次出现。 lastIndexOf()方法从列表的末尾搜索元素。两个方法都返回-1如果 List 不包含指定的对象。 subList(int fromIndex,int toIndex)返回一个子列表的原始列表从索引fromIndex(包括)到索引toIndex(独占)。 ListIterator 从 List 接口可以返回在向前和向后方向上遍历其元素。 ArrayList和LinkedList 以下是实现 List 接口的两个类: ArrayList LinkedList ArrayList由数组备份。LinkedList由链接列表备份。 如果我们频繁地访问列表的元素,那么 ArrayList 会表现得更好。访问ArrayList中的元素更快,因为它是数组后端。 从 ArrayList 添加或删除元素更慢除非从头到尾,因为 ArrayList 必须执行数组副本内部保持元素的顺序。 LinkedList 的性能优于 ArrayList 用于添加和从列表中间删除元素。但是,访问列表中的元素更慢,除非在列表的头部。 import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("Java"); list.add("Oracle"); list.add("CSS"); list.add("XML"); System.out.println("List: " + list); int count = list.size(); System.out.println("Size of List: " + count); // Print each element with its index for (int i = 0; i < count; i++) { String element = list.get(i); System.out.println("Index=" + i + ", Element=" + element); } List<String> subList = list.subList(1, 3); System.out.println(subList); // Remove "CSS" from the list list.remove("CSS"); // Same as list.remove(2); System.out.println(list); } } 结果: List: [Java, Oracle, CSS, XML] Size of List: 4 Index=0, Element=Java Index=1, Element=Oracle Index=2, Element=CSS Index=3, Element=XML [Oracle, CSS] [Java, Oracle, XML] ListIterator 我们可以使用 ListIterator 接口以遍历列表。 ListIterator 接口继承了 Iterator 接口并且它增加了几个方法来从当前位置向后访问列表中的元素。 以下代码显示了如何从列表中获取列表迭代器: ListIterator<String> fullIterator = list.listIterator(); 为了得到在正向从索引5开始的列表迭代器,使用以下代码。 ListIterator<String> partialIterator = list.listIterator(5); 以下代码显示如何使用 ListIterator 。 import java.util.ArrayList; import java.util.List; import java.util.ListIterator; public class Main { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("Oracle"); list.add("SQL"); list.add("CSS"); list.add("XML"); System.out.println("List: " + list); // Get the list iterator ListIterator<String> iterator = list.listIterator(); while (iterator.hasNext()) { int index = iterator.nextIndex(); String element = iterator.next(); System.out.println("Index=" + index + ", Element=" + element); } // Reuse the iterator to iterate from the end to the beginning while (iterator.hasPrevious()) { int index = iterator.previousIndex(); String element = iterator.previous(); System.out.println("Index=" + index + ", Element=" + element); } } } 结果: List: [Oracle, SQL, CSS, XML] Index=0, Element=Oracle Index=1, Element=SQL Index=2, Element=CSS Index=3, Element=XML Index=3, Element=XML Index=2, Element=CSS Index=1, Element=SQL Index=0, Element=Oracle ListIterator 可以向前看或回头一个列表。 next()方法向前移动一个索引,而 previous()方法向后移动一个索引。 如果使用 next()方法,后跟 previous()方法,迭代器返回到相同的位置。
队列是只能在其上执行操作的对象的集合两端的队列。 队列有两个末端,称为头和尾。 在简单队列中,对象被添加到尾部并从头部删除并首先删除首先添加的对象。 Java Collections Framework支持以下类型的队列。 简单的队列允许在尾部插入和从头部移除。 优先级队列为每个元素分配优先级,并允许从队列中删除具有最高优先级的元素。 延迟队列向每个元素添加延迟,并仅在其延迟已过去时删除该元素。 双端队列允许其元件从头部和尾部插入和移除。 阻塞队列阻塞线程,当线程已满时向其添加元素,当线程为空时,它阻止线程从中删除元素。 传输队列是阻塞队列,其中对象的切换发生在生产者线程和消费者线程之间。 阻塞双端队列是双端队列和阻塞队列的组合。 简单队列 简单队列由 Queue 接口的实例表示。 队列允许您执行三个基本操作: 从尾部添加元素 从其头部移除元素 在元素顶部审查 例子 import java.util.LinkedList; import java.util.NoSuchElementException; import java.util.Queue; public class Main { public static void main(String[] args) { Queue<String> queue = new LinkedList<>(); queue.add("Java"); // offer() will work the same as add() queue.offer("SQL"); queue.offer("CSS"); queue.offer("XML"); System.out.println("Queue: " + queue); // Let"s remove elements until the queue is empty while (queue.peek() != null) { System.out.println("Head Element: " + queue.peek()); queue.remove(); System.out.println("Removed one element from Queue"); System.out.println("Queue: " + queue); } System.out.println("queue.isEmpty(): " + queue.isEmpty()); System.out.println("queue.peek(): " + queue.peek()); System.out.println("queue.poll(): " + queue.poll()); try { String str = queue.element(); System.out.println("queue.element(): " + str); str = queue.remove(); System.out.println("queue.remove(): " + str); } catch (NoSuchElementException e) { System.out.println("queue.remove(): Queue is empty."); } } } 结果: Queue: [Java, SQL, CSS, XML] Head Element: Java Removed one element from Queue Queue: [SQL, CSS, XML] Head Element: SQL Removed one element from Queue Queue: [CSS, XML] Head Element: CSS Removed one element from Queue Queue: [XML] Head Element: XML Removed one element from Queue Queue: [] queue.isEmpty(): true queue.peek(): null queue.poll(): null queue.remove(): Queue is empty.