首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在针对每个键删除某些项之后从一个映射中收集值,并使用流生成另一个映射(Java 8)

如何在针对每个键删除某些项之后从一个映射中收集值,并使用流生成另一个映射(Java 8)
EN

Stack Overflow用户
提问于 2015-01-16 12:34:44
回答 2查看 259关注 0票数 0

我有地图。在对应于每个键的地图中,有一个包含50个对象的列表。基本上是我用溪流制作的地图。我所做的,我使用了流的groupingBy函数。以下是我所采取的步骤。

代码语言:javascript
复制
Map<Long, List<Learner>> learnersMap = learnersDataList.stream()
            .collect(Collectors.groupingBy(Learner::getLearnerEnrollmentId));

然后,我使用下面的代码对每个键分离出小于50计数或等于50计数的记录。

代码语言:javascript
复制
Map<Long, List<Learner>> answersLessThan50CountLearnersMap = 
             learnersMap.entrySet()
            .stream()
            .filter(p -> p.getValue().stream().count() < 50)
            .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()));

代码语言:javascript
复制
Map<Long, List<Learner>> validLearnersMap = 
            learnersMap.entrySet()
            .stream()
            .filter(p -> p.getValue().stream().count() == 50)
            .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()));

现在我要从answersLessThan50CountLearnersMap生成一个地图,它只包含列表中的一条记录。我是说,如果Map看起来像这样

代码语言:javascript
复制
1-->[Learner, Learner, Learner, ....]
2-->[Learner, Learner, Learner, ....]
3-->[Learner, Learner, Learner, ....]

我想要制作一张这样的地图

代码语言:javascript
复制
1--> Learner
2--> Learner
3--> Learner

实际上,列表中的所有记录都是多余的。就像名字一样,在所有50个学习者中,反对键1的对象是相同的。只有一个记录是不同的,但我不需要它,因为我必须通过从学习对象获得学习记录发送电子邮件,而不需要那个独特的记录。密钥23也是如此。就像我可以说的

代码语言:javascript
复制
entrySet.getValue.stream.findFirst() or entrySet.getValue.stream.limit(1)

对于entrySet.In中的每个条目,我想从answersLessThan50CountLearnersMap生成像Map<Long, Learner>这样的地图

我可以通过将流操作应用到它来完成它吗?请帮帮忙

谢谢

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-01-16 14:24:07

请考虑一下,并不是因为您使用的是Streams,一切都会更好。

在我看来,第一件事是p.getValue().stream().count(),而p.getValue()实际上返回了一个List。因此,p.getValue().size()在这里显然更合理。

此外,如果您只需要List的第一个元素,那么调用list.get(0)是一种行之有效的方法,比list.stream().findFirst()更简单。如果列表的大小可能为零,则必须检查这一点,但在其中一种情况下,它已经被证明为非零(因为size等于Predicate强制要求的50 )。

在定义Map应该包含哪些值时,您可以正确地这样做:

代码语言:javascript
复制
Map<Long, Learner> answersLessThan50CountLearnersMap = 
     learnersMap.entrySet().stream()
    .filter(p -> p.getValue().size() < 50)
    .collect(Collectors.toMap(p -> p.getKey(),
                              p -> p.getValue().isEmpty()? null: p.getValue().get(0)));
Map<Long, Learner> validLearnersMap = 
    learnersMap.entrySet().stream()
    .filter(p -> p.getValue().size() == 50)// implies non-empty list
    .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue().get(0)));

如果您想为了效率而放弃紧凑性,您可能会认为您只对每个元素的第一个元素感兴趣,就在创建第一个映射时,换句话说,您所需要的只是第一个元素和计数,而不是一个完全填充的List。因此,我们需要另一个容器,只保存第一个元素和计数,适合于收集数据:

代码语言:javascript
复制
class LearnerAndCount {
    Learner first;
    int count;
    LearnerAndCount add(Learner l) {
        if(first==null) first=l;
        count++;
        return this;
    }
    LearnerAndCount merge(LearnerAndCount lac) {
        if(first==null) first=lac.first;
        count+=lac.count;
        return this;
    }
}

收集信息

代码语言:javascript
复制
Map<Long, LearnerAndCount> learnersMap = learnersDataList.stream().collect(
  Collectors.groupingBy(Learner::getLearnerEnrollmentId,
    Collector.of(LearnerAndCount::new, LearnerAndCount::add, LearnerAndCount::merge)));

并将其用于创建两个映射。

代码语言:javascript
复制
Map<Long, Learner> answersLessThan50CountLearnersMap = 
     learnersMap.entrySet().stream()
    .filter(p -> p.getValue().count < 50)
    .collect(Collectors.toMap(Map.Entry::getKey, p -> p.getValue().first));
Map<Long, Learner> validLearnersMap = 
     learnersMap.entrySet().stream()
    .filter(p -> p.getValue().count == 50)
    .collect(Collectors.toMap(Map.Entry::getKey, p -> p.getValue().first));
票数 1
EN

Stack Overflow用户

发布于 2015-01-16 13:14:07

但我不知道它有多好,因为我是新来的溪流。这就是我所做的。

代码语言:javascript
复制
Map<Long, Learner> invalidLearnersMap = 
            answersLessThan50CountLearnersMap.entrySet()
            .stream()
            .collect(Collectors.toMap(p -> p.getKey(), p ->  {
                Optional<Learner> learner = p.getValue().stream().findFirst();
                if (learner.isPresent()) {
                    Learner learner = learner.get();
                    return learner;
                } else {
                    return null;
                }

            }));

在我获得lessThan50CountMap的地方,我也可以做到这一点。不管怎样,谢谢。

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

https://stackoverflow.com/questions/27984090

复制
相关文章

相似问题

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