Java 一步完成分组和筛选

Java 一步完成分组和筛选,java,lambda,java-8,java-stream,collectors,Java,Lambda,Java 8,Java Stream,Collectors,我有一个流,我想要一个地图。让我们调用我的分类器函数getKey(String)——它可能很昂贵。有时它返回零,这意味着字符串应该被丢弃,而不包括在结果映射中 因此,我可以使用以下代码: Stream<String> stringStream; Map<Integer, String> result = stringStream.collect(Collectors.groupingBy(this::getKey, Collectors.joining());

我有一个
,我想要一个
地图
。让我们调用我的分类器函数
getKey(String)
——它可能很昂贵。有时它返回零,这意味着字符串应该被丢弃,而不包括在结果映射中

因此,我可以使用以下代码:

Stream<String> stringStream;
Map<Integer, String> result = 
    stringStream.collect(Collectors.groupingBy(this::getKey, Collectors.joining());
result.remove(0);
Stream-stringStream;
映射结果=
collect(Collectors.groupingBy(this::getKey,Collectors.joining());
结果:删除(0);
这首先将不需要的字符串添加到以零为键的映射中,然后删除它们。可能有很多字符串。有没有一种优雅的方法可以避免将它们添加到映射中


我不想在分组之前添加筛选步骤,因为这意味着执行决策/分类代码两次。

您说过调用
getKey
代价很高,但您仍然可以在筛选之前预先映射流的元素。在这种情况下,对
getKey
的调用将只执行一次

Map<Integer, String> result =
    stringStream.map(s -> new SimpleEntry<>(this.getKey(s), s))
                .filter(e -> e.getKey() != 0)
                .collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, joining()))); 

您可以使用这样的配对流:

stringStream.map(x -> new Pair(getKey(x), x))
            .filter(pair -> pair.left != 0) // or whatever predicate
            .collect(Collectors.groupingBy(pair -> pair.left,
                        Collectors.mapping(pair -> pair.right, Collectors.joining())));
此代码假定简单的
类具有两个字段
left
right

有些第三方库(如my)提供了删除样板文件的其他方法:

StreamEx.of(stringStream)
        .mapToEntry(this::getKey, x -> x)
        .filterKeys(key -> key != 0) // or whatever
        .grouping(Collectors.joining());

您是否考虑过运行
map
将流从
stream
更改为元组流,然后调用groupBy并通过临时对象访问?
StreamEx.of(stringStream)
        .mapToEntry(this::getKey, x -> x)
        .filterKeys(key -> key != 0) // or whatever
        .grouping(Collectors.joining());