拨开荷叶行,寻梦已然成。仙女莲花里,翩翩白鹭情。
IMG-LOGO
主页 文章列表 Stream API中的mapMulti指南

Stream API中的mapMulti指南

白鹭 - 2021-11-06 2205 0 2

1. 概述

在本教程中,我们将回顾 我们将编写简单的示例来说明如何使用它。特别是,我们将介绍在什么情况下我们更喜欢使用Stream::mapMultiStream:: flatMapmapMultiflatMap

请务必查看我们关于Java Streams

2. 方法签名

省略通配符,mapMulti

<R> Stream<R> mapMulti(BiConsumer<T, Consumer<R>> mapper)

这是一个 功能接口的实现作为参数。的实现采用StreamBiConsumerBiConsumerStreamTtype Rmapper'Consumer::accept

在Java 的mapMultimapperConsumer

每次我们调用Consumer::accept,

3. 简单实现示例

让我们考虑一个整数列表来执行以下操作:

List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5); double percentage = .01;
List<Double> evenDoubles = integers.stream()
.<Double>mapMulti((integer, consumer) -> {
if (integer % 2 == 0) {
consumer.accept((double) integer * ( 1 + percentage));
}
})
.collect(toList());

BiConsumer<T, Consumer<R>> mapper的lambda 实现中,我们首先只选择偶数整数,然后我们将指定的数量添加到percentagedouble,consumer.accept

正如我们之前看到的,(作为旁注,请注意我们必须使用类型见证consumer<Double>mapMultiR

根据元素是奇数还是偶数,这是一对零或一对一转换。

请注意,前面代码示例中 因此,我们可以使用if statement Stream::filterStream::mapStream's filtermap

List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5); double percentage = .01;
List<Double> evenDoubles = integers.stream()
.filter(integer -> integer % 2 == 0)
.<Double>map(integer -> ((double) integer * ( 1 + percentage)))
.collect(toList());

然而,mapMulti

另一个优点是**mapMulti

为了支持intlongdoublemapMultiToDoublemapMultiToInt,mapMultiToLongmapMulti

例如,我们可以使用mapMultiToDoubleList

List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5); double percentage = .01; double sum = integers.stream()
.mapMultiToDouble((integer, consumer) -> {
if (integer % 2 == 0) {
consumer.accept(integer * (1 + percentage));
}
})
.sum();

4. 更现实的例子

让我们考虑一个Album

public class Album {
private String albumName; private int albumCost; private List<Artist> artists;
Album(String albumName, int albumCost, List<Artist> artists) { this.albumName = albumName; this.albumCost = albumCost; this.artists = artists;
}
// ...
}

每个AlbumArtist

public class Artist {
private final String name; private boolean associatedMajorLabels; private List<String> majorLabels;
Artist(String name, boolean associatedMajorLabels, List<String> majorLabels) { this.name = name; this.associatedMajorLabels = associatedMajorLabels; this.majorLabels = majorLabels;
}
// ...
}

如果我们想收集艺术家-专辑名称对的列表,我们可以使用mapMulti

List<Pair<String, String>> artistAlbum = albums.stream()
.<Pair<String, String>> mapMulti((album, consumer) -> {
for (Artist artist : album.getArtists()) {
consumer.accept(new ImmutablePair<String, String>(artist.getName(), album.getAlbumName()));
}
})

对于流中的每个专辑,我们遍历艺术家,创建 的实现累积消费者接受的元素并将它们传递给流管道。ImmutablePaironsumer::acceptmapMulti

这具有一对多转换的效果,其中结果在消费者中累积,但最终被扁平化为新的流。这本质上是Stream::flatMap

List<Pair<String, String>> artistAlbum = albums.stream()
.flatMap(album -> album.getArtists()
.stream()
.map(artist -> new ImmutablePair<String, String>(artist.getName(), album.getAlbumName())))
.collect(toList());

我们看到这两种方法给出了相同的结果。接下来我们将介绍在哪些情况下使用mapMulti

5. 何时使用mapMultiflatMap

5.1.用少量元素替换流元素

正如Java 文档中所述:“当用少量(可能为零)元素替换每个流元素时。使用这种方法可以避免为每组结果元素Stream flatMap”.

让我们写一个简单的例子来说明这个场景:

int upperCost = 9;
List<Pair<String, String>> artistAlbum = albums.stream()
.<Pair<String, String>> mapMulti((album, consumer) -> {
if (album.getAlbumCost() < upperCost) { for (Artist artist : album.getArtists()) {
consumer.accept(new ImmutablePair<String, String>(artist.getName(), album.getAlbumName()));
}
}
})

对于每张专辑,我们迭代艺术家并积累零个或几个艺术家-专辑对,这取决于专辑的价格与变量upperCost

flatMap完成相同的结果:

int upperCost = 9;
List<Pair<String, String>> artistAlbum = albums.stream()
.flatMap(album -> album.getArtists()
.stream()
.filter(artist -> upperCost > album.getAlbumCost())
.map(artist -> new ImmutablePair<String, String>(artist.getName(), album.getAlbumName())))
.collect(toList());

我们看到**mapMultiflatMap

5.2.何时更容易生成结果元素

让我们在Album

public class Album {
//...
public void artistAlbumPairsToMajorLabels(Consumer<Pair<String, String>> consumer) {
for (Artist artist : artists) { if (artist.isAssociatedMajorLabels()) {
String concatLabels = artist.getMajorLabels().stream().collect(Collectors.joining(","));
consumer.accept(new ImmutablePair<>(artist.getName()+ ":" + albumName, concatLabels));
}
}
}
// ...
}

如果艺术家与主要标签有关联,则实现会将标签连接到逗号分隔的字符串中。然后它创建一对带有标签的艺术家专辑名称并调用Consumer::accept

如果我们想获得所有对的列表,就像使用mapMultiAlbum::artistAlbumPairsToMajorLabels

List<Pair<String, String>> copyrightedArtistAlbum = albums.stream()
.<Pair<String, String>> mapMulti(Album::artistAlbumPairsToMajorLabels)
.collect(toList());

我们看到,在更复杂的情况下,我们可以有非常复杂的方法引用实现。例如,

latMap复制相同的结果会非常困难。要求以**flatMap .**StreammapMulti **flatMap** .


标签:

0 评论

发表评论

您的电子邮件地址不会被公开。 必填的字段已做标记 *