我有一张地图。在映射中对应于每个键,有一个包含50个对象的List。基本上我使用Streams制作了这张地图。我做了什么,我使用了流的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
开始,我生成一个只包含List中一条记录的地图。我的意思是假设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中的每个条目。换句话说,我想从Map<Long, Learner>
answersLessThan50CountLearnersMap
之类的地图
我可以通过对其应用流操作来实现。请帮忙
由于
答案 0 :(得分:1)
请注意,并非因为您使用的是Stream
s。
跳入我眼中的第一件事是p.getValue().stream().count()
,而p.getValue()
实际上会返回List
。所以p.getValue().size()
在这里显然更合理。
此外,如果您只想要List
的第一个元素,则调用list.get(0)
是一种行之有效的方法,比list.stream().findFirst()
更简单。如果列表的大小可能为零,则必须检查,但在您的一个案例中,它已被证明是非零的(因为size
等于50
强制要求{ {1}})。
您可以在定义Predicate
应包含的值的位置执行此操作:
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)));
答案 1 :(得分:0)
但我不知道因为我是溪流的新手有多好。这就是我做的。
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
。无论如何谢谢。