Java 8 从映射中的匹配值中提取第一个键

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

Java 8 extract first key from matching value in a Map

javalambdajava-8java-streamoptional

提问by Julian

Suppose I have a map of given name, surname pairs and I want to find the given name of the first entry in that map that has the surname matching a certain value. How would we do this in a java 8 fashion.

假设我有一张名字、姓氏对的地图,我想在该地图中找到姓氏与某个值匹配的第一个条目的名字。我们将如何以 Java 8 方式执行此操作。

In my test case example below I put two ways that would do it.

在我下面的测试用例示例中,我提出了两种方法。

However the first one (looking for the given name of the first person with a surname of "Donkey") will throw java.util.NoSuchElementException: No value present so it is not safe.

但是,第一个(查找姓氏为“Donkey”的第一个人的给定名称)将抛出 java.util.NoSuchElementException: No value present so 它不安全。

The second one works but it is not only harder to read but it it is a bit not quite functional.

第二个有效,但它不仅难以阅读,而且有点不太实用。

Just wondering if someone here would suggest me an easier clearer way of achieving this using either stream()or forEach()or both.

只是不知道是否有人在这里会建议我实现这个要么使用一个更简单更清晰的方式stream()forEach()或两者兼而有之。

@Test
public void shouldBeAbleToReturnTheKeyOfTheFirstMatchingValue() throws Exception {
    Map<String, String> names = new LinkedHashMap<>();
    names.put("John", "Doe");
    names.put("Fred", "Flintstone");
    names.put("Jane", "Doe");
    String keyOfTheFirst = names.entrySet().stream().filter(e -> e.getValue().equals("Doe")).findFirst().get().getKey();
    assertEquals("John", keyOfTheFirst);

    try {
        names.entrySet().stream().filter(e -> e.getValue().equals("Donkey")).findFirst().get();
    } catch (NoSuchElementException e){
        // Expected
    }

    Optional<Map.Entry<String, String>> optionalEntry = names.entrySet().stream().filter(e -> e.getValue().equals("Donkey")).findFirst();
    keyOfTheFirst = optionalEntry.isPresent() ? optionalEntry.get().getKey() : null;

    assertNull(keyOfTheFirst);
}

Thank you in advance.

先感谢您。

采纳答案by Misha

To return a default value if there is no match, use Optional#orElse

如果没有匹配,要返回默认值,请使用 Optional#orElse

names.entrySet().stream()
  .filter(e -> e.getValue().equals("Donkey"))
  .map(Map.Entry::getKey)
  .findFirst()
  .orElse(null);

回答by Doon

From a similar question:

从一个类似的问题

public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) {
    return map.entrySet()
              .stream()
              .filter(entry -> Objects.equals(entry.getValue(), value))
              .map(Map.Entry::getKey)
              .collect(Collectors.toSet());
}

Then you can select the first, if you want to. Remember that the keyis unique, the valueis not.

然后你可以选择第一个,如果你愿意。请记住,这key是独一无二的,value不是。

Edit: The whole code (thanks @Peter Lawrey)

编辑:整个代码(感谢@Peter Lawrey)

package test;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

public class Main {

    public static void main(String[] args) {
        Map<String, String> names = new LinkedHashMap<>();
        names.put("John", "Doe");
        names.put("Fred", "Flintstone");
        names.put("Jane", "Doe");

        Optional<String> firstKey = names.entrySet().stream()
                .filter(entry -> Objects.equals(entry.getValue(), "Doe"))
                .map(Map.Entry::getKey).findFirst();

        if (firstKey.isPresent()) {
            System.out.println(firstKey.get());
        }
    }
}

回答by saka1029

I like old fashioned:

我喜欢老式:

static <K, V> K findFirstKeyByValue(Map<K, V> map, String value) {
    for (Entry<K, V> e : map.entrySet())
        if (e.getValue().equals(value))
            return e.getKey();
    return null;
}

回答by Tagir Valeev

The solution provided by @Misha is the best one if you don't want to use the third-party code. My libraryhas the special shortcut method ofKeysfor such cases as I discovered that it's quite common task:

如果您不想使用第三方代码,@Misha 提供的解决方案是最好的解决方案。我的库ofKeys为这种情况提供了特殊的快捷方法,因为我发现这是一项非常常见的任务:

StreamEx.ofKeys(names, "Donkey"::equals).findFirst().orElse(null);

回答by Pavan T

Below is my code snippet to get key from map,

下面是我从地图中获取密钥的代码片段,

Map<String,String> pageDetails = new HashMap<String,String>();

public String getAssociatedKey(){
pageDetails.entrySet().stream().filter( e -> e.getValue().contains("John").findFirst().get().getKey();
}

回答by Dhanumjaya

In order to avoid null pointer exception if map entry exist with null value:

如果映射条目存在空值,为了避免空指针异常:

private String getValueByKey(Map<String, String> map, String key)
{
        return map.entrySet().stream().filter(e -> 
        StringUtils.equalsIgnoreCase(e.getKey(), key)).findFirst().get()
                .getValue();
}