要求是使用流使用多个匹配条件从Map列表中获取所有匹配和非匹配记录。即不是只有一个过滤器来比较“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@domain.com","id":"A2"},
{"Email":"test1@domain.com","id":"B1"}]
使用流,我能够找到匹配和不匹配的记录,使用电子邮件的单个筛选谓词:匹配记录:
[{"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;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class ListFiltersToGetMatchingRecords {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
List<Map<String, Object>> dbRecords = createDbRecords();
List<Map<String, Object>> inputRecords = createInputRecords();
List<Map<String,Object>> matchinRecords = dbRecords.parallelStream().filter(searchData ->
inputRecords.parallelStream().anyMatch(inputMap ->
searchData.get("Email").equals(inputMap.get("Email")))).
collect(Collectors.toList());
List<Map<String,Object>> 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("Matching Records: " + matchinRecords.size());
matchinRecords.forEach(record -> {
System.out.println(record.get("Email"));
});
System.out.println("Non Matching Records" + notMatchinRecords.size());
notMatchinRecords.forEach(record -> {
System.out.println(record.get("Email"));
});
System.out.println("Non Matching Records" + notMatchinRecords.size());
System.out.println("Matching Records: " + matchinRecords.size());
System.out.println("TotalTImeTaken =" + ((endTime-startTime) /1000) + "sec");
}
private static List<Map<String, Object>> createDbRecords() {
List<Map<String, Object>> dbRecords = new ArrayList<>();
for(int i =0; i< 100; i+=2) {
Map<String, Object> dbRecord = new HashMap<>();
dbRecord.put("Email","naveen" + i +"@gmail.com");
dbRecord.put("Id", "ID" + i);
dbRecords.add(dbRecord);
}
return dbRecords;
}
private static List<Map<String, Object>> createInputRecords() {
List<Map<String, Object>> dbRecords = new ArrayList<>();
for(int i =0; i< 100; i++) {
Map<String, Object> dbRecord = new HashMap<>();
dbRecord.put("Email", "naveen" + i +"@gmail.com");
dbRecord.put("ID", "ID" + i);
dbRecords.add(dbRecord);
}
return dbRecords;
}
}
为什么不在anymatch
中使用&
:
anyMatch(inputMap -> searchData.get("Email").equals(inputMap.get("Email"))
&& searchData.get("Id").equals(inputMap.get("Id")))
我怀疑您是否真的需要ParallelStream
,另一方面,您确实需要System.nanoTime
而不是CurrentTimeMillis
如果你关心性能,你不应该把一个线性搜索和另一个线性搜索结合起来;因此,当列表变大时,复杂度无法通过并行处理来固定。
您应该首先构建一个允许高效查找的数据结构:
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());
此解决方案将保留映射
的标识。
如果您只对与“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());
我陷入了java流操作的边缘案例... 我想对以下行为进行编码:“从一个任意的水果篮子中,收集20个最小的,除了最小的梨,因为我们不想那样。” 额外的奖励:来的篮子可能没有任何梨。 null 我不能使用本地布尔值并在筛选第一个pear后将其设置为,因为lambda中的所有局部变量都必须是final的。 最坏的情况是,我可以将篮子一分为二,梨和非梨,对梨进行排序,如果有的话,适当地将它们子列表。这看
问题内容: 我想获取两个列表并查找两个列表中都出现的值。 [5]例如,将返回。 问题答案: 使用,它快速且可读。
问题内容: 我正在努力从我们的数据库中淘汰某个客户。我注意到一种趋势,人们用与他们填写公司名称相同的名字来填写名字。因此,示例如下所示: 这些人是我不想被查询的人。他们是坏蛋。我正在尝试将查询与WHERE语句(大概)组合在一起,以隔离姓氏至少与公司名称部分匹配的人,但是我很困惑,可以使用一些帮助。 问题答案: 您可以采用基于相似性的方法 在答案底部尝试代码 它会产生如下结果 因此,您将能够根据相似
我的目标是筛选出最佳匹配。在我的例子中,我有一个人员列表,我想按姓氏和名字过滤。 匹配的预趋势将是: < li >姓和名都匹配,返回第一个匹配项 < li >仅姓氏匹配,返回第一个匹配项 < li >不匹配,抛出一些异常 我目前为止的代码:
嗨,我有两个自定义数组列表,我想从一个数组列表中删除与第二个数组列表匹配的类似项。
我有一个接口,它提供了一个方法,返回一个,其中包含一个