Java 8 从 Map 中的匹配值中提取所有键

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/49329728/
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-11-03 10:20:14  来源:igfitidea点击:

Java 8 extract all keys from matching values in a Map

javalambdajava-8java-stream

提问by Srinivas Lakshman

I'm relatively new to Java8 and I have a scenario where I need to retrieve all the keys from the Map which matched with the objects.

我对 Java8 比较陌生,我有一个场景,我需要从 Map 中检索与对象匹配的所有键。

Wanted to know if there is a way to get all keys without iterating them from the list again.

想知道是否有办法获取所有键而无需再次从列表中迭代它们。

Person.java
private String firstName;
private String lastName;
//setters and getters & constructor


MAIN Class.

String inputCriteriaFirstName = "john";   

Map<String, Person> inputMap = new HashMap<>();
Collection<Person> personCollection = inputMap.values();
List<Person> personList = new ArrayList<>(personCollection);
List<Person> personOutputList = personList.stream()
.filter(p -> p.getFirstName().contains(inputCriteriaFirstName ))
.collect(Collectors.toList());


//IS There a BETTER way to DO Below ??

Set<String> keys = new HashSet<>();
for(Person person : personOutputList) {
    keys.addAll(inputMap.entrySet().stream().filter(entry -> Objects.equals(entry.getValue(), person))
        .map(Map.Entry::getKey).collect(Collectors.toSet()));
}

采纳答案by Eugene

inputMap.entrySet() 
        .stream()
        .filter(entry -> personOutputList.contains(entry.getValue()))
        .map(Entry::getKey)
        .collect(Collectors.toCollection(HashSet::new))

回答by Sahil Aggarwal

You can also use foreachapi provided in java8 under lambda's

您还可以在 lambda 下使用java8 中提供的foreachapi

Below is code for your main method :

以下是您的主要方法的代码:

public static  void main() {

        String inputCriteriaFirstName = "john";   

        Map<String, Person> inputMap = new HashMap<>();
        Set<String> keys = new HashSet<>();

        inputMap.forEach((key,value) -> {
            if(value.getFirstName().contains(inputCriteriaFirstName)){
                keys.add(key);
            }
        });
    }

回答by Eran

Instead of iterating over all the entries of the Map for each Person, I suggest iterating over the Map once:

Person我建议迭代 Map 一次,而不是为 each迭代Map 的所有条目:

Set<String> keys =
     inputMap.entrySet()
             .stream()
             .filter(e -> personOutputList.contains(e.getValue()))
             .map(Map.Entry::getKey)
             .collect(Collectors.toCollection(HashSet::new));

This would still result in quadratic running time (since List.contains()has linear running time). You can improve that to overall linear running time if you create a HashSetcontaining the elements of personOutputList, since containsfor HashSettakes constant time.

这仍然会导致二次运行时间(因为List.contains()具有线性运行时间)。如果您创建一个HashSet包含 的元素,您可以将其提高到整体线性运行时间personOutputList,因为containsforHashSet需要恒定的时间。

You can achieve that by changing

你可以通过改变来实现

List<Person> personOutputList = 
    personList.stream()
              .filter(p -> p.getFirstName().contains(inputCriteriaFirstName))
              .collect(Collectors.toList());

to

Set<Person> personOutputSet = 
    personList.stream()
              .filter(p -> p.getFirstName().contains(inputCriteriaFirstName))
              .collect(Collectors.toCollection(HashSet::new));

回答by Andreas

So, you want a personOutputListwith all the selected persons, and a keysset with the keys for those selected persons?

那么,您想要一个personOutputList包含所有选定人员的keys集合,以及一个包含这些选定人员的键的集合?

Best (for performance) option is to not discard the keys during search, then split the result into separate person list and key set.

最佳(为了性能)选项是在搜索期间不丢弃键,然后将结果拆分为单独的人员列表和键集。

Like this:

像这样:

String inputCriteriaFirstName = "john";
Map<String, Person> inputMap = new HashMap<>();

Map<String, Person> tempMap = inputMap.entrySet()
        .stream()
        .filter(e -> e.getValue().getFirstName().contains(inputCriteriaFirstName))
        .collect(Collectors.toMap(Entry::getKey, Entry::getValue));
List<Person> personOutputList = new ArrayList<>(tempMap.values());
Set<String> keys = new HashSet<>(tempMap.keySet());

The keysset is explicitly made an updatable copy. If you don't need that, drop the copying of the key values:

keys集合被明确地制作为可更新的副本。如果您不需要,请删除键值的复制:

Set<String> keys = tempMap.keySet();