在Java8流中,如何比较两个映射列表来识别具有多个筛选谓词的匹配记录和非匹配记录
需求是使用流使用多个匹配条件从映射列表中获取所有匹配和非匹配记录。i、 e而不是只有一个过滤器只比较“Email”,需要比较两个列表来匹配记录,并使用多个过滤器谓词来比较Email和Id 清单1:在Java8流中,如何比较两个映射列表来识别具有多个筛选谓词的匹配记录和非匹配记录,java,java-8,Java,Java 8,需求是使用流使用多个匹配条件从映射列表中获取所有匹配和非匹配记录。i、 e而不是只有一个过滤器只比较“Email”,需要比较两个列表来匹配记录,并使用多个过滤器谓词来比较Email和Id 清单1: [{"Email","naveen@domain.com", "Id": "A1"}, {"Email":"test@domain.com","id":"A2"}] 清单2: [{"Email","naveen@domain.com", "Id": "A1"}, {"Email":"test
[{"Email","naveen@domain.com", "Id": "A1"},
{"Email":"test@domain.com","id":"A2"}]
清单2:
[{"Email","naveen@domain.com", "Id": "A1"},
{"Email":"test@domain.com","id":"A2"},
{"Email":"test1@domain.com","id":"B1"}]
使用streams,我可以在电子邮件上使用单个筛选器谓词查找匹配和不匹配的记录:
匹配记录:
[{"Email","naveen@domain.com", "Id": "A1"},
{"Email":"test@domain.com","id":"A2"}]
不匹配记录:
[{"Email":"test1@domain.com","id":"B1"}]]
有没有一种方法可以同时比较电子邮件和Id,而不仅仅是电子邮件
dbRecords.parallelStream().filter(searchData ->
inputRecords.parallelStream().anyMatch(inputMap ->
searchData.get("Email").equals(inputMap.get("Email")))).
collect(Collectors.toList());
import java.util.ArrayList;
导入java.util.HashMap;
导入java.util.List;
导入java.util.Map;
导入java.util.stream.collector;
公共类ListFiltersToGetMatchingRecords{
公共静态void main(字符串[]args){
long startTime=System.currentTimeMillis();
List dbRecords=createDbRecords();
List inputRecords=createInputRecords();
List matchinRecords=dbRecords.parallelStream().filter(搜索数据->
inputRecords.parallelStream().anyMatch(inputMap->
searchData.get(“Email”).equals(inputMap.get(“Email”))。
collect(Collectors.toList());
List notMatchinRecords=inputRecords.parallelStream().filter(searchData->
dbRecords.parallelStream().noneMatch(inputMap->
searchData.get(“Email”).equals(inputMap.get(“Email”))
)).collect(Collectors.toList());
long-endTime=System.currentTimeMillis();
System.out.println(“匹配记录:+matchinRecords.size());
matchinRecords.forEach(记录->{
System.out.println(record.get(“Email”);
});
System.out.println(“非匹配记录”+notMatchinRecords.size());
notMatchinRecords.forEach(记录->{
System.out.println(record.get(“Email”);
});
System.out.println(“非匹配记录”+notMatchinRecords.size());
System.out.println(“匹配记录:+matchinRecords.size());
System.out.println(“totaltimetake=“+((endTime startTime)/1000)+“sec”);
}
私有静态列表createDbRecords(){
List dbRecords=new ArrayList();
对于(int i=0;i<100;i+=2){
Map dbRecord=newhashmap();
dbRecord.put(“Email”,“naveen”+i+“@gmail.com”);
dbRecord.put(“Id”,“Id”+i);
添加(dbRecord);
}
返回数据库记录;
}
私有静态列表createInputRecords(){
List dbRecords=new ArrayList();
对于(int i=0;i<100;i++){
Map dbRecord=newhashmap();
dbRecord.put(“Email”,“naveen”+i+“@gmail.com”);
dbRecord.put(“ID”,“ID”+i);
添加(dbRecord);
}
返回数据库记录;
}
}
为什么不在任何匹配中使用&&
:
anyMatch(inputMap -> searchData.get("Email").equals(inputMap.get("Email"))
&& searchData.get("Id").equals(inputMap.get("Id")))
我怀疑您是否真的需要parallelStream
,您确实需要System.nanoTime
,而不是currentTimeMillis
您只需要在比较中添加一个条件
dbRecords.parallelStream().filter(searchData ->
inputRecords.parallelStream().anyMatch(inputMap ->
searchData.get("Email").equals(inputMap.get("Email"))
&& searchData.get("id").equals(inputMap.get("id"))))
.collect(Collectors.toList());
- 将其添加到
noneMatch()
中李>
- 使用
System.nanoTime()
计算平均时间,这样更精确
- 尝试使用和不使用
.parallelStream()
(仅使用.stream()
),因为不确定它是否有帮助)
如果您关心性能,则不应将线性搜索与另一个线性搜索相结合;因此,当列表变大时,并行处理无法修复由此产生的时间复杂性
您应该首先构建一个允许高效查找的数据结构:
Map<List<?>,Map<String, Object>> inputKeys = inputRecords.stream()
.collect(Collectors.toMap(
m -> Arrays.asList(m.get("ID"),m.get("Email")),
m -> m,
(a,b) -> { throw new IllegalStateException("duplicate "+a+" and "+b); },
LinkedHashMap::new));
List<Map<String,Object>> matchinRecords = dbRecords.stream()
.filter(m -> inputKeys.containsKey(Arrays.asList(m.get("ID"),m.get("Email"))))
.collect(Collectors.toList());
matchinRecords.forEach(m -> inputKeys.remove(Arrays.asList(m.get("ID"),m.get("Email"))));
List<Map<String,Object>> notMatchinRecords = new ArrayList<>(inputKeys.values());
第一个变体可以扩展以轻松支持更多/其他地图条目:
List<String> keys = Arrays.asList("ID", "Email");
Function<Map<String,Object>,List<?>> getKey
= m -> keys.stream().map(m::get).collect(Collectors.toList());
Map<List<?>,Map<String, Object>> inputKeys = inputRecords.stream()
.collect(Collectors.toMap(
getKey,
m -> m,
(a,b) -> { throw new IllegalStateException("duplicate "+a+" and "+b); },
LinkedHashMap::new));
List<Map<String,Object>> matchinRecords = dbRecords.stream()
.filter(m -> inputKeys.containsKey(getKey.apply(m)))
.collect(Collectors.toList());
matchinRecords.forEach(m -> inputKeys.remove(getKey.apply(m)));
List<Map<String,Object>> notMatchinRecords = new ArrayList<>(inputKeys.values());
List key=Arrays.asList(“ID”、“Email”);
函数,Map>inputKeys=inputRecords.stream()
.collect(collector.toMap)(
getKey,
m->m,
(a,b)->{抛出新的非法状态例外(“重复”+a+”和“+b);},
LinkedHashMap::new));
列表matchinRecords=dbRecords.stream()
.filter(m->inputKeys.containsKey(getKey.apply(m)))
.collect(Collectors.toList());
matchinRecords.forEach(m->inputKeys.remove(getKey.apply(m));
List notmatchinerecords=newarraylist(inputKeys.values());
这里是mate。。。
比较两个映射列表以识别Java8流中具有多个筛选器谓词的匹配和非匹配记录的最有效方法是:
List unMatchedRecords=dbRecords.parallelStream().filter(searchData->
inputRecords.parallelStream().noneMatch(inputMap->
searchData.entrySet().stream().noneMatch(值->
inputMap.entrySet().stream().noneMatch(值1->
(value1.getKey().equals(value.getKey())&&
value1.getValue().equals(value.getValue()))
)).collect(Collectors.toList());
注意:
如果。。。anyMatch(inputMap->searchData.get(“Email”).equals(inputMap.get(“Email”))和&searchData.get(“Id”).equals(inputMap.get(“Id”))
?Id
或Id
?在你的帖子中我看到了所有3个:使用多个过滤器不是一个可行的选择,因为比较键/字段是动态的,这意味着这些键在运行时会动态变化。根据列表中存在的字段,必须使用“Email”或“Id”或“Email”和“Id”。在这种情况下,如何应用多个过滤器,假设我得到的比较键是一个字符串列表。由于两个线性搜索的组合具有二次时间复杂度,可以想象OP进入paralle所在的区域
Map<Object,Object> notMatchinRecords = inputRecords.stream()
.collect(Collectors.toMap(
m -> m.get("ID"),
m -> m.get("Email"),
(a,b) -> { throw new IllegalStateException("duplicate"); },
LinkedHashMap::new));
Object notPresent = new Object();
Map<Object,Object> matchinRecords = dbRecords.stream()
.filter(m -> notMatchinRecords.getOrDefault(m.get("ID"), notPresent)
.equals(m.get("Email")))
.collect(Collectors.toMap(
m -> m.get("ID"),
m -> m.get("Email"),
(a,b) -> { throw new IllegalStateException("duplicate"); },
LinkedHashMap::new));
notMatchinRecords.keySet().removeAll(matchinRecords.keySet());
System.out.println("Matching Records: " + matchinRecords.size());
matchinRecords.forEach((id,email) -> System.out.println(email));
System.out.println("Non Matching Records" + notMatchinRecords.size());
notMatchinRecords.forEach((id,email) -> System.out.println(email));
List<String> keys = Arrays.asList("ID", "Email");
Function<Map<String,Object>,List<?>> getKey
= m -> keys.stream().map(m::get).collect(Collectors.toList());
Map<List<?>,Map<String, Object>> inputKeys = inputRecords.stream()
.collect(Collectors.toMap(
getKey,
m -> m,
(a,b) -> { throw new IllegalStateException("duplicate "+a+" and "+b); },
LinkedHashMap::new));
List<Map<String,Object>> matchinRecords = dbRecords.stream()
.filter(m -> inputKeys.containsKey(getKey.apply(m)))
.collect(Collectors.toList());
matchinRecords.forEach(m -> inputKeys.remove(getKey.apply(m)));
List<Map<String,Object>> notMatchinRecords = new ArrayList<>(inputKeys.values());
List<Map<String,String>> unMatchedRecords = dbRecords.parallelStream().filter(searchData ->
inputRecords.parallelStream().noneMatch( inputMap ->
searchData.entrySet().stream().noneMatch(value ->
inputMap.entrySet().stream().noneMatch(value1 ->
(value1.getKey().equals(value.getKey()) &&
value1.getValue().equals(value.getValue()))))
)).collect(Collectors.toList());