我有地图。在对应于每个键的地图中,有一个包含50个对象的列表。基本上是我用溪流制作的地图。我所做的,我使用了流的groupingBy
函数。以下是我所采取的步骤。
Map<Long, List<Learner>> learnersMap = learnersDataList.stream()
.collect(Collectors.groupingBy(Learner::getLearnerEnrollmentId));
然后,我使用下面的代码对每个键分离出小于50计数或等于50计数的记录。
Map<Long, List<Learner>> answersLessThan50CountLearnersMap =
learnersMap.entrySet()
.stream()
.filter(p -> p.getValue().stream().count() < 50)
.collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()));
和
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看起来像这样
1-->[Learner, Learner, Learner, ....]
2-->[Learner, Learner, Learner, ....]
3-->[Learner, Learner, Learner, ....]
我想要制作一张这样的地图
1--> Learner
2--> Learner
3--> Learner
实际上,列表中的所有记录都是多余的。就像名字一样,在所有50个学习者中,反对键1的对象是相同的。只有一个记录是不同的,但我不需要它,因为我必须通过从学习对象获得学习记录发送电子邮件,而不需要那个独特的记录。密钥2
和3
也是如此。就像我可以说的
entrySet.getValue.stream.findFirst() or entrySet.getValue.stream.limit(1)
对于entrySet.In中的每个条目,我想从answersLessThan50CountLearnersMap
生成像Map<Long, Learner>
这样的地图
我可以通过将流操作应用到它来完成它吗?请帮帮忙
谢谢
发布于 2015-01-16 06:24:07
请考虑一下,并不是因为您使用的是Stream
s,一切都会更好。
在我看来,第一件事是p.getValue().stream().count()
,而p.getValue()
实际上返回了一个List
。因此,p.getValue().size()
在这里显然更合理。
此外,如果您只需要List
的第一个元素,那么调用list.get(0)
是一种行之有效的方法,比list.stream().findFirst()
更简单。如果列表的大小可能为零,则必须检查这一点,但在其中一种情况下,它已经被证明为非零(因为size
等于Predicate
强制要求的50
)。
在定义Map
应该包含哪些值时,您可以正确地这样做:
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
。因此,我们需要另一个容器,只保存第一个元素和计数,适合于收集数据:
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;
}
}
收集信息
Map<Long, LearnerAndCount> learnersMap = learnersDataList.stream().collect(
Collectors.groupingBy(Learner::getLearnerEnrollmentId,
Collector.of(LearnerAndCount::new, LearnerAndCount::add, LearnerAndCount::merge)));
并将其用于创建两个映射。
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));
发布于 2015-01-16 05:14:07
但我不知道它有多好,因为我是新来的溪流。这就是我所做的。
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
的地方,我也可以做到这一点。不管怎样,谢谢。
https://stackoverflow.com/questions/27984090
复制相似问题