如何通过 Java 8 中的值过滤地图?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33459961/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 14:41:33  来源:igfitidea点击:

How to filter a map by its values in Java 8?

javajava-8

提问by Nazila

I have a map where the values are strings and the keys are lists: Map<String, List<BoMLine>> materials. I'd like to filter this map by its values; something like this:

我有一张地图,其中值是字符串,键是列表:Map<String, List<BoMLine>> materials. 我想通过它的值过滤这张地图;像这样:

materials.entrySet().stream()
       .filter(a->a.getValue().stream()
           .filter(l->MaterialDao.findMaterialByName(l.getMaterial()).ispresent)

But it's not working for me. Does anybody have an idea?

但这对我不起作用。有人有想法吗?

Thank you.

谢谢你。

采纳答案by Eran

If I understand your filtering criteria correctly, you want to check if the filtered Streamyou produced from the value Listhas any elements, and if so, pass the corresponding Mapentry to the output Map.

如果我正确理解您的过滤条件,您想检查Stream您从该值生成的过滤器是否List有任何元素,如果有,将相应的Map条目传递给 output Map

Map<String, List<BoMLine>>
    filtered = materials.entrySet()
                        .stream()
                        .filter(a->a.getValue()
                                    .stream()
                                    .anyMatch(l->MaterialDao.findMaterialByName(l.getMaterial())))
                        .collect(Collectors.toMap(e->e.getKey(),e->e.getValue()));

This is assuming MaterialDao.findMaterialByName(l.getMaterial())returns a boolean.

这是假设MaterialDao.findMaterialByName(l.getMaterial())返回一个boolean.

回答by Nazila

finally made it work,my second filter was completely useless the answer is like this:

终于成功了,我的第二个过滤器完全没用,答案是这样的:

Map<String, List<BoMLine>>
filtered = materials.entrySet()
                    .stream()
                    .filter(a -> a
                      .getValue()
                       .stream()
                        .allMatch(
                            b -> MaterialDao.findMaterialByName(
                                    b.getMaterial()).isPresent()))
            .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue()))

回答by Matthias Braun

Generally, this is how you can filter a map by its values:

通常,这是按值过滤地图的方法:

static <K, V> Map<K, V> filterByValue(Map<K, V> map, Predicate<V> predicate) {
    return map.entrySet()
            .stream()
            .filter(entry -> predicate.test(entry.getValue()))
            .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
}

Call it like this:

像这样调用它:

Map<String, Integer> originalMap = new HashMap<>();
originalMap.put("One", 1);
originalMap.put("Two", 2);
originalMap.put("Three", 3);

Map<String, Integer> filteredMap = filterByValue(originalMap, value -> value == 2);

Map<String, Integer> expectedMap = new HashMap<>();
expectedMap.put("Two", 2);

assertEquals(expectedMap, filteredMap);

回答by rustyx

All the previous answers provide a solution that creates a new Map. This may be inefficient if you want to remove just a few entries.

以前的所有答案都提供了一个解决方案,可以创建一个新的Map. 如果您只想删除几个条目,这可能效率低下。

The following removes the elements from the existingMap:

以下内容从现有 中删除元素Map

Map<String, Integer> myMap = new HashMap<>();
myMap.put("One", 1);
myMap.put("Two", 2);
myMap.put("Three", 3);

myMap.keySet().removeAll(
        myMap.entrySet().stream()
           .filter(a->a.getValue().equals(2))
                   .map(e -> e.getKey()).collect(Collectors.toList()));

System.out.println(myMap);

Prints:

印刷:

{One=1, Three=3}

How does it work? It collects all keysthat need to be removed into a temporary List, then removes them from the original Mapin one go. A temporary Listis required because modifying a Mapinvalidates streams and iterators. However, building a new Mapis potentially a much more costly operation that building a List.

它是如何工作的?它将所有需要删除的密钥收集到一个临时 中List,然后Map一次性将它们从原始密钥中删除。临时List是必需的,因为修改 aMap会使流和迭代器无效。但是,Map与构建List.

If you want to remove a lot of entries (50% or more), then it's better to build a new Mapindeed.

如果您想删除大量条目(50% 或更多),那么最好Map确实构建一个新条目。