1. 概述
在本教程中,我们将回顾 我们将编写简单的示例来说明如何使用它。特别是,我们将介绍在什么情况下我们更喜欢使用Stream::mapMulti
Stream::
flatMap
mapMulti
flatMap
请务必查看我们关于Java Streams
2. 方法签名
省略通配符,mapMulti
<R> Stream<R> mapMulti(BiConsumer<T, Consumer<R>> mapper)
这是一个 功能接口的实现作为参数。的实现采用Stream
BiConsumer
BiConsumer
Stream
T
type
R
mapper'
Consumer::accept
在Java 的mapMulti
mapper
Consumer
每次我们调用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 实现中,我们首先只选择偶数整数,然后我们将指定的数量添加到percentage
double,
consumer.accept
正如我们之前看到的,(作为旁注,请注意我们必须使用类型见证consumer
<Double>mapMulti
R
根据元素是奇数还是偶数,这是一对零或一对一转换。
请注意,前面代码示例中 因此,我们可以使用if statement
Stream::filter
Stream::map
Stream's
filter
map
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
为了支持int
long
double
mapMultiToDouble
mapMultiToInt,
mapMultiToLong
mapMulti
例如,我们可以使用mapMultiToDouble
List
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;
}
// ...
}
每个Album
Artist
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()));
}
})
对于流中的每个专辑,我们遍历艺术家,创建 的实现累积消费者接受的元素并将它们传递给流管道。ImmutablePair
onsumer::accept
mapMulti
这具有一对多转换的效果,其中结果在消费者中累积,但最终被扁平化为新的流。这本质上是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. 何时使用mapMulti
flatMap
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());
我们看到**mapMulti
flatMap
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
如果我们想获得所有对的列表,就像使用mapMulti
Album::artistAlbumPairsToMajorLabels
List<Pair<String, String>> copyrightedArtistAlbum = albums.stream()
.<Pair<String, String>> mapMulti(Album::artistAlbumPairsToMajorLabels)
.collect(toList());
我们看到,在更复杂的情况下,我们可以有非常复杂的方法引用实现。例如,
latMap
复制相同的结果会非常困难。要求以**flatMap .**
Stream
mapMulti
**flatMap** .
0 评论