在Java8+;
我有一张在Java8+;,java,java-stream,Java,Java Stream,我有一张地图和一张列表。我想根据条件划分映射 foreach(map.key -> list.contains(map.key)) 并生成两张地图。最优雅的方式是什么?我使用的是Java11,所以您可以在答案中输入您想要的任何内容 我现在想到的是: map.entrySet() .stream() .collect(partitioningBy(e -> list.contains(o.getKey()))); 但是这会产生一个映射你不可能真正使用流生成两个单独的映射
地图
和一张列表
。我想根据条件划分映射
foreach(map.key -> list.contains(map.key))
并生成两张地图。最优雅的方式是什么?我使用的是Java11,所以您可以在答案中输入您想要的任何内容
我现在想到的是:
map.entrySet()
.stream()
.collect(partitioningBy(e -> list.contains(o.getKey())));
但是这会产生一个
映射
你不可能真正使用流生成两个单独的映射(至少不是以最优雅的方式)。不要害怕使用旧的常规forEach
,我认为它是一个相当干净的版本:
Map<String, String> contains = new HashMap<>();
Map<String, String> containsNot = new HashMap<>();
for(Map.Entry<String, String> entry : yourMap.entrySet()) {
if (yourList.contains(entry.getKey())) {
contains.put(entry.getKey(), entry.getValue());
} else {
containsNot.put(entry.getKey(), entry.getValue());
}
}
Map contains=newhashmap();
Map containsNot=new HashMap();
for(Map.Entry:yourMap.entrySet()){
if(yourList.contains(entry.getKey())){
包含.put(entry.getKey(),entry.getValue());
}否则{
containsNot.put(entry.getKey(),entry.getValue());
}
}
您可以使用toMap
减少每个组(作为下游收集器):
Map myMap=newhashmap();
myMap.put(“d”、“d”);
myMap.put(“c”、“c”);
myMap.put(“b”、“b”);
myMap.put(“A”、“A”);
List myList=Arrays.asList(“a”、“b”、“c”);
Map result=myMap.entrySet()
.stream()
.collect(收集器(
entry->myList.contains(entry.getKey()),
toMap(条目::getKey,条目::getValue)
)
);
对于这个例子,它产生
{false={A=A,d=d},true={b=b,c=c}}
您可以通过对原始映射应用过滤来过滤映射
,例如:
List<String> list = new ArrayList<>(); //List of values
Map<String, String> map = new HashMap<>();
Map<String, String> filteredMap = map.entrySet()
.stream()
.filter(e -> list.contains(e.getKey()))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
List List=new ArrayList()//价值清单
Map Map=newhashmap();
Map filteredMap=Map.entrySet()
.stream()
.filter(e->list.contains(e.getKey()))
.collect(Collectors.toMap(条目::getKey,条目::getValue));
然后,您可以将filteredMap
内容与原始map
进行比较,以提取filteredMap
中不存在的条目,作为@ernest_k答案的补充。您可以使用函数和groupingBy
:
Map<String, String> myMap = new HashMap<>();
myMap.put("d", "D");
myMap.put("c", "C");
myMap.put("b", "B");
myMap.put("A", "A");
List<String> myList = Arrays.asList("a", "b", "c");
Function<Entry<String, String> , Boolean> myCondition = i -> myList.contains(i.getKey());
Map<Boolean,List<Entry<String, String>>> myPartedMap = myMap.entrySet()
.stream().collect(Collectors.groupingBy(myCondition));
System.out.println(myPartedMap);
Map myMap=newhashmap();
myMap.put(“d”、“d”);
myMap.put(“c”、“c”);
myMap.put(“b”、“b”);
myMap.put(“A”、“A”);
List myList=Arrays.asList(“a”、“b”、“c”);
函数myCondition=i->myList.contains(i.getKey());
Map myPartedMap=myMap.entrySet()
.stream().collect(收集器.groupingBy(myCondition));
System.out.println(myPartedMap);
但是当您需要根据条件将两个备选方案作为输出时,可以使用分区方式。然而,另一种解决方法(对于基于单个条件创建地图很有用)是使用收集器
Map<String, String> myMap = Map.of("d", "D","c", "C","b", "B","A", "A");
List<String> myList = List.of("a", "b", "c");
Predicate<String> condition = myList::contains;
Map<String, String> keysPresentInList = myMap.keySet()
.stream()
.collect(Collectors.filtering(condition,
Collectors.toMap(Function.identity(), myMap::get)));
Map<String, String> keysNotPresentInList = myMap.keySet()
.stream()
.collect(Collectors.filtering(Predicate.not(condition),
Collectors.toMap(Function.identity(), myMap::get)));
您可以迭代映射并使用Java 8+中引入的优点:
Map<Boolean, Map<String, String>> result = Map.of(true, new LinkedHashMap<>(),
false, new LinkedHashMap<>());
Set<String> set = new HashSet<>(list);
map.forEach((k, v) -> result.get(set.contains(k)).put(k, v));
Map result=Map.of(真,新LinkedHashMap(),
false,新建LinkedHashMap());
Set Set=新哈希集(列表);
map.forEach((k,v)->result.get(set.contains(k)).put(k,v));
首先,我们创建一个result
映射,其中包含两个条目,每个分区一个条目。这些值是LinkedHashMap
s,以便保留插入顺序
然后,我们从列表中创建一个HashSet
,这样调用set.contains(k)
就是一个O(1)
操作(否则,如果我们做了list.contains(k)
,那么对于映射的每个条目,这将是O(n)
,从而产生总时间复杂度O(n^2)
,这是不好的)
最后,根据调用set的结果,我们迭代输入映射并将(k,v)
条目放入相应的分区中。contains(k)
请阅读您能用实际数据给出一个您想要实现的示例吗?在这里我不必全速前进:一条流创建一个结果,但你想要两张地图?!请参阅相关stackoverflow.com/questions/28856781。最佳方法取决于地图和列表的大小,以及如何使用结果。例如,Guava Maps可以简单而快速地在原始地图上提供2个过滤视图,以避免额外的内存使用,但如果在结果中多次调用contains(),则可能会有非常糟糕的性能。我猜使用stream().filter(…).collect(…)也一样?@asoob确实如此。根据Darshan的回答,这种方法的性能很差O(n*m),当对于HashMaps和input,给定get()和contains()有O(1)时,O(m)的解决方案是可能的。见stackoverflow.com/questions/28856781
myMap.keySet().retainAll(myList);
Map<Boolean, Map<String, String>> result = Map.of(true, new LinkedHashMap<>(),
false, new LinkedHashMap<>());
Set<String> set = new HashSet<>(list);
map.forEach((k, v) -> result.get(set.contains(k)).put(k, v));