首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >java 11 lambda,按相同属性聚合和满足一定条件的过滤器

java 11 lambda,按相同属性聚合和满足一定条件的过滤器
EN

Stack Overflow用户
提问于 2020-10-09 18:49:00
回答 3查看 59关注 0票数 0

我有以下实体:

代码语言:javascript
运行
复制
ID    | PROPERTY

FOO   | A
FOO   | Z
JOHN  | A
DOE   | Z

现在,我想按ID对这些实体进行分组,如果存在一个或两个值,则获取属性为'A‘的实体,否则为Z。

因此,输出应为:

代码语言:javascript
运行
复制
FOO   | A
JOHN  | A
DOE   | Z

我在考虑groupingBy流方法,但我不知道如何使用什么收集器,如果也不是正确的解决方案:

代码语言:javascript
运行
复制
list.stream()
            .collect(Collectors.groupingBy(o -> o.getId(), ? another collector function ?)
            .collect(Collectors.toList()));
EN

回答 3

Stack Overflow用户

发布于 2020-10-09 19:07:44

试试这个:

代码语言:javascript
运行
复制
entities.stream()
        .collect(toMap(YourEntityType::getId, 
                       YourEntityType::getProperty,
                       (x, y) -> "A".equals(x) ? x : y));

更新:

我刚刚注意到@Holger在他的评论中发布了完全相同的东西,而我正在编辑我的答案。不过,这里有两个小区别:

  • 我更喜欢使用方法引用而不是lambda(这是一个品味问题,但我发现它们比lambdas)
  • "A".equals(x)更不容易出错,比更安全。如果xnull.

,则NPE将导致后者失败

更新2:

既然您想要列表形式的结果,那么此选项应该适用于您:

代码语言:javascript
运行
复制
entities.stream()
        .collect(collectingAndThen(
                    toMap(YourEntityType::getId, 
                          identity(),
                          (x, y) -> "A".equals(x.getProperty()) ? x : y,
                    m -> new ArrayList<YourEntityType>(m.values()));
票数 1
EN

Stack Overflow用户

发布于 2020-10-09 20:25:05

如果您坚持使用分组收集器,则? another collector function ?将如下所示:

代码语言:javascript
运行
复制
    public static void main(String[] args) {
        record C(String id, String property) {}
        List<C> list = List.of(new C("FOO","A"),new C("FOO","Z"),new C("JOHN","A"),new C("DOE","Z"),new C("XXX","X"));
        System.out.println(list);
        Object result = list.stream()
                .collect(Collectors.groupingBy(o -> o.id, Collectors.collectingAndThen(Collectors.reducing((l,r) -> "A".equals(l.property) ? l : r), Optional::get)));
        System.out.println(result);     
    }

,这一想法建议纠正几乎@ETO的解决方案。

(抱歉,我有记录,我懒得使用getter。)

票数 1
EN

Stack Overflow用户

发布于 2020-10-10 21:59:35

代码语言:javascript
运行
复制
// Utility class with methods you can reuse for other purposes too
public final class StreamUtil {

    private StreamUtil() {}

    public static <T, U> Predicate<T> distinctBy(Function<T, U> keyFunction) {
        final Set<U> uniqueKeys = synchronizedSet(new HashSet<>());
        return item -> uniqueKeys.add(keyFunction.apply(item));
    }
}

和您的问题的解决方案

代码语言:javascript
运行
复制
entities.stream()
 .sorting(Comparator.comparing(Entity::getProperty)) // order entities according to priorities
 .filter(StreamUtil.distinctBy(Entity::getId)) // take first entity only per key
 ... // here you have stream as per you requirements. You can collect() it or continue mapping/filtering

由于排序的原因,此解决方案比此处建议的其他解决方案要慢。然而,它有它的优势-更容易阅读,而速度慢只会在大型集合上发挥作用。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64278525

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档