简介
一个流表示一个元素的序列,并支持不同类型的操作,以达到预期的结果。流的源头通常是一个集合或一个数组,数据从那里流出来。
流在几个方面与集合不同;最明显的是,流不是一个存储元素的数据结构。它们在本质上是功能性的,值得注意的是,对一个流的操作会产生一个结果,通常会返回另一个流,但不会修改其来源。
为了 "巩固 "这些变化,你把一个流的元素收集回一个Collection 。
在本指南中,我们将看看如何在Java 8中收集流元素到地图中。
采集器和Stream.collect()
收集器代表了Collector 接口的实现,它实现了各种有用的缩减操作,例如将元素累积到集合中,根据特定参数总结元素,等等。
所有预定义的实现都可以在
Collectors类中找到。
你也可以非常容易地实现你自己的收集器,并使用它来代替预定义的收集器--你可以用内置的收集器走得很远,因为它们涵盖了你可能想要使用它们的绝大多数情况。
为了能够在我们的代码中使用这个类,我们需要导入它。
import static java.util.stream.Collectors.*;
Stream.collect() 在流的元素上执行一个可变的还原操作。
可变还原操作在处理流中的元素时,将输入元素收集到一个可变容器中,比如Collection 。
*Collectors.toSet()*的指南
toSet() 方法是用来将一个流收集成一个集合。它的工作方式与toList() 方法类似,但最终会收集到一个不同的底层数据结构中,通过返回一个Collector ,将输入的元素累积到一个新的Set 。
值得注意的是,对返回的Set 的类型、可变性、可序列化或线程安全都没有保证。
public static <T> Collector<T,?,Set<T>> toSet()
一个
Set,不允许有重复的元素,或者用更正式的术语来说--集合不包含任何一对元素a和b,这样a.equals(b),而且它最多可以包含一个null元素。
如果你把一个有重复元素的流收集到一个Set - 这是一个快速修剪掉重复元素的方法。
Stream<String> stream =
Stream.of("This", "forms", "forms", "a", "short", "a", "sentence", "sentence");
Set<String> sentenceSet = stream.collect(Collectors.toSet());
然而,这个例子强调了Sets填充方式的一个重要特征--元素在收集时不会像在toList() 收集器中那样保留其相对顺序。这是因为Set 的默认实现是HashSet ,它根据元素的哈希值来排序,甚至不能保证这个顺序在一段时间内的一致性。
我们将在后面的章节中看一下我们如何提供一个自定义的
Set。
运行这段代码的结果是
[sentence, a, This, short, forms]
由于我们很少只处理字符串或原始对象--让我们定义一个简单的类来表示一个Book 。
public class Book {
private String title;
private String author;
private int releaseYear;
private int soldCopies;
// Constructor, getters and setters
}
有了它,我们就可以创建一个简单的几本书的列表(有一个重复的条目)。
List<Book> books = Arrays.asList(
new Book("The Fellowship of the Ring", "J.R.R. Tolkien", 1954, 30),
new Book("The Hobbit", "J.R.R. Tolkien", 1937, 40),
new Book("Animal Farm", "George Orwell", 1945, 32),
new Book("Nineteen Eighty-Four", "George Orwell", 1949, 50),
new Book("Nineteen Eighty-Four", "George Orwell", 1949, 38)
);
Predicate 一个相当典型的流水线包括一个基于一些filter() ,然后再收集回一个集合。
Set<String> booksGeorgeOrwell = books.stream()
.filter(book->book.getAuthor()
.equals("George Orwell") && book.getCopiesSold() >= 30)
.map(Book::getTitle).collect(Collectors.toSet());
System.out.println(booksGeorgeOrwell);
正如我们前面所讨论的,Set,不允许有重复的内容。在我们检查了我们给出的子句以及List 中的哪些书符合标准后,我们应该有以下结果。
[Animal Farm, Nineteen Eighty-Four]
效果很好!重复的条目被修剪掉了,没有明确的逻辑来修剪掉重复的条目。
结论
在本指南中,我们已经看了如何使用Java 8的Streams API和Collectors 类来收集流并将其转换为一个Set。