繁体   English   中英

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

[英]Java 8 extract first key from matching value in a Map

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

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

然而,第一个(寻找姓氏为“Donkey”的第一个人的名字)将抛出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);
}

先感谢您。

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

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

如果您不想使用第三方代码,@ Miki提供的解决方案是最好的解决方案。 我的图书馆有专门的快捷方法ofKeys对于这样的情况,因为我发现,这是很常见的任务:

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

来自一个类似的问题

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

然后,如果您愿意,可以选择第一个。 请记住, key是唯一的, value不是。

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

我喜欢老式的:

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM