从具有相似对象 ID 的两个列表中获取映射



我是java stream API的新手。 我有 2 个列表,如果它们的内部对象 ID 都匹配,则希望将一些属性放入 MAP。 下面是实现。

List<LookupMstEntity> examTypeDetails; //This list contains values init.
List<MarksMstEntity> marksDetailList;  //This list contains values init.
//FYI above entities have lombok setter, getter, equals & hashcode.
Map<Long, Integer> marksDetailMap = new HashMap<>();
//need below implementation to changed using java 8.
for (LookupMstEntity examType : examTypeDetails) {
for (MarksMstEntity marks : marksDetailList) {
if (examType.getLookupId() == marks.getExamTypeId())
marksDetailMap.put(examType.getLookupId(), marks.getMarks());
}
}

创建一组 lookupIdSet<Long> ids可帮助您丢弃重复值并摆脱不必要的检查。

然后,您可以使用examTypeId值相应地过滤marksDetailList

filter(m -> ids.contains(m.getExamTypeId()))

哈希集contains()方法具有恒定的时间复杂度O(1(。

试试这个:

Set<Long> ids = examTypeDetails.stream().map(LookupMstEntity::getLookupId)
.collect(Collectors.toCollection(HashSet::new));
Map<Long, Integer> marksDetailMap = marksDetailList.stream().filter(m -> ids.contains(m.getExamTypeId()))
.collect(Collectors.toMap(MarksMstEntity::getExamTypeId, MarksMstEntity::getMarks));

只要您正在寻找具有相同 ID 的这些,那么使用哪个 ID 并不重要。我建议您先开始流式传输marksDetailList,因为您需要它的getMarks()。筛选方法搜索 ID 中是否存在匹配项。如果是这样,请将所需的键值收集到地图中。

Map<Long, Integer> marksDetailMap = marksDetailList.stream() // List<MarksMstEntity>
.filter(mark -> examTypeDetails.stream()                 // filtered those where ...
.map(LookupMstEntity::getLookupId)                   // ... the lookupId
.anyMatch(id -> id == mark.getExamTypeId()))         // ... is present in the list
.collect(Collectors.toMap(                               // collected to Map ...
MarksMstEntity::getExamTypeId,                       // ... with ID as a key
MarksMstEntity::getMarks));                          // ... and marks as a value

.map(..).anyMatch(..)可以缩小为一个:

.anyMatch(exam -> exam.getLookupId() == mark.getExamTypeId())

如评论中所述,为了简洁起见,我宁愿进行每次迭代,因为您已经使用了。

观察结果:

首先,生成的映射指示 ID 类型只能有一个匹配项(否则您将具有重复的键,并且该值需要是合并重复键的List或其他方式,而不是Integer。 因此,当您找到第一个并将其插入地图中时,请打破内部循环。

for (LookupMstEntity examType : examTypeDetails) {  
for (MarksMstEntity marks : marksDetailList) {
if (examType.getLookupId() == marks.getExamTypeId()) {
marksDetailMap.put(examType.getLookupId(),
marks.getMarks());
// no need to keep on searching for this ID
break;
}
}
}

此外,如果您的两个类由可以访问id的父类或共享接口相关联,并且这两个类被视为基于该idequal,那么您可以执行类似操作。

for (LookupMstEntity examType : examTypeDetails) {
int index = marksDetailList.indexOf(examType);
if (index > 0) {
marksDetailMap.put(examType.getLookupId(),
marksDetaiList.get(index).getMarks());
}
}

当然,查找索引的负担仍然存在,但现在它在引擎盖下,您被免除了这一责任。

您可以使用HashMapO(N)时间复杂度来做到这一点,首先将两个列表转换为Map<Integer, LookupMstEntity>,然后以 id 作为键Map<Integer, MarksMstEntity>

Map<Integer, LookupMstEntity> examTypes = examTypeDetails.stream()
.collect(Collectors.toMap(LookupMstEntity::getLookupId, 
Function.identity())  //make sure you don't have any duplicate LookupMstEntity objects with same id
Map<Integer, MarksMstEntity> marks = marksDetailList.stream()
.collect(Collectors.toMap(MarksMstEntity::getExamTypeId, 
Function.identity())   // make sure there are no duplicates

然后流式传输examTypes地图,然后收集到地图中MarksMstEntity如果地图中存在具有相同 idmarks

Map<Integer, Integer> result = examTypes.entrySet()
.stream()
.map(entry->new AbstractMap.SimpleEntry<Integer, MarksMstEntity>(entry.getKey(), marks.get(entry.getKey())))
.filter(entry->entry.getValue()!=null)
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

最新更新