要求是使用流使用多个匹配条件从“地图列表”中获取所有匹配和不匹配的记录。即,不是使用单个过滤器来只比较“电子邮件”,而是需要比较两个列表以匹配记录,并比较多个过滤谓词来比较电子邮件和ID。
列表1:
fuzzy(sample[3], sample[4])
列表2:
[{"Email","naveen@domain.com", "Id": "A1"},
{"Email":"test@domain.com","id":"A2"}]
使用流,我可以使用Email上的Single filter谓词查找匹配和不匹配的记录: 匹配记录:
[{"Email","naveen@domain.com", "Id": "A1"},
{"Email":"test@domain.com","id":"A2"},
{"Email":"test1@domain.com","id":"B1"}]
不匹配的记录:
[{"Email","naveen@domain.com", "Id": "A1"},
{"Email":"test@domain.com","id":"A2"}]
是否可以同时比较电子邮件和ID比较,而不只是电子邮件
[{"Email":"test1@domain.com","id":"B1"}]]
dbRecords.parallelStream().filter(searchData ->
inputRecords.parallelStream().anyMatch(inputMap ->
searchData.get("Email").equals(inputMap.get("Email")))).
collect(Collectors.toList());
答案 0 :(得分:3)
如果您关心性能,则不应将线性搜索与另一个线性搜索结合使用;当列表变大时,使用并行处理无法解决由此带来的时间复杂性。
您应该建立一个数据结构,该结构首先允许高效查找:
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());
此解决方案将保留Map
的身份。
如果您只对与"Email"
键相关联的值感兴趣,那会简单得多:
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());
答案 1 :(得分:0)
为什么不在&&
内使用anyMatch
:
anyMatch(inputMap -> searchData.get("Email").equals(inputMap.get("Email"))
&& searchData.get("Id").equals(inputMap.get("Id")))
我怀疑您实际上是否需要parallelStream
,另一方面您确实需要System.nanoTime
而不是currentTimeMillis
答案 2 :(得分:0)
您只需要在比较中添加一个条件
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()
),因为不确定它是否可以帮助您答案 3 :(得分:0)
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());
注意:
如果上面使用的
这样获得的不匹配记录可以很容易地从列表中的任何一个(即dbRecords或inputRecords)中减去,以检索匹配结果,并且操作迅速。
干杯
Shubham Chauhan