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

2022-09-01 15:00:15

假设我有一个名字,姓氏对的地图,我想找到该地图中姓氏与某个值匹配的第一个条目的名字。我们如何以java 8的方式做到这一点。

在下面的测试用例示例中,我提出了两种方法来做到这一点。

然而,第一个(寻找第一个姓氏为“驴子”的人的名字)将抛出java.util.NoSuchElementException:没有值存在,所以它不安全。

第二个有效,但它不仅更难阅读,而且它有点功能性差。

只是想知道这里是否有人会建议我使用其中一种或两者来实现这一目标的更简单,更清晰的方法。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);
}

提前感谢您。


答案 1

若要在没有匹配项时返回默认值,请使用 Optional#orElse

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

答案 2

从类似的问题

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());
}

然后,如果需要,可以选择第一个。请记住,是唯一的,不是。keyvalue

编辑:整个代码(感谢@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());
        }
    }
}

推荐