1.3 filter(), map(), 和 flatMap() 方法

1.3 filter(), map(), 和 flatMap() 方法

流的转换将产生一个新流,其元素来自于另一个流的元素。 你已经看到了过滤器转换流,该转换将产生具有符合特定条件的那些元素的新流。 在这里,我们将字符串流转换为仅包含长单词的另一个流:

1
2
List<String> words = ...;
Stream<String> longWords = words.stream().filter(w -> w.length() > 12);

filter 的参数为泛型,即从 T 到 boolean 的函数。

通常,你想通过某种方式来转化流中的值,使用 map() 方法并对流进行转化。例如,你可以通过以下的例子来将所有的单词转化为小写。

1
Stream<String> lowercaseWords = words.stream().map(String::toLowerCase);

在这里,我们引用了 map() 方法。通常情况下,你可以使用 lambda 表达式来替代它。

1
Stream<String> firstLetters = words.stream().map(s -> s.substring(0, 1));

结果中将包含每一个单词的首字母。

使用 map() 时,会将一个函数应用于每个元素,结果是带有结果的新流。 现在,假设您有一个函数,该函数不仅返回一个值,还返回一串值,例如:

1
2
3
4
5
6
7
8
public static Stream<String> letters(String s)
{
List<String> result = new ArrayList<>();
for (int i = 0; i < s.length(); i++)
result.add(s.substring(i, i + 1));
return result.stream();
}
letters("boat") is the stream ["b", "o", "a", "t"].

使用第1.13节 “IntStream” 中的IntStream.range方法,你可以更优雅地实现此方法。

假设你把 letters() 方法映射到字符串流上。

1
Stream<Stream<String>> result = words.stream().map(w -> letters(w));

您将获得一个流中的流,例如[… [“ y”,“ o”,“ u”,“ r”],[“ b”,“ o”,“ a”,“ t”] 、。 ..]将其展平为字母流[…“ y”,“ o”,“ u”,“ r”,“ b”,“ o”,“ a”,“ t”,.. ],请使用flatMap方法代替map:

1
2
Stream<String> flatResult = words.stream().flatMap(w -> letters(w))
// Calls letters on each word and flattens the results

你将在流之外的其他类中找到flatMap方法。 它是计算机科学中的一般概念。 假设您具有通用类型G(例如Stream),并且函数f从某些类型T到G ,而g从U到G 。 然后,你可以编写它们,首先使用 flatMap() 应用f,然后应用g。 这是 monad 理论的关键思想。 但请放心,您可以在不了解 monad 的情况下使用 flatMap。

1
2
3
4
5
6
7
java.util.stream.Stream 8
Stream<T> filter(Predicate<? super T> predicate)
//产生一个包含该流中满足特定元素的流。
• <R> Stream<R> map(Function<? super T,? extends R> mapper)
//产生一个包含将 mapper 应用于此流的元素的结果的流。
• <R> Stream<R> flatMap(Function<? super T,? extends Stream<? extends R>> mapper)
//产生一个流,该流是通过将应用mapper的结果连接到该流的元素而获得的。 (请注意,每个结果都是一个流。)
坚持原创技术分享,您的支持将鼓励我继续创作!