Java 8 从映射中的匹配值中提取第一个键
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);
}
提前致谢。
来自类似的 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());
}
然后你可以 select 第一个,如果你愿意的话。请记住 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;
}
给return一个默认值如果没有匹配,使用Optional#orElse
names.entrySet().stream()
.filter(e -> e.getValue().equals("Donkey"))
.map(Map.Entry::getKey)
.findFirst()
.orElse(null);
如果你不想使用第三方代码,@Misha 提供的解决方案是最好的解决方案。 My library has the special shortcut method ofKeys
对于这种情况,我发现这是很常见的任务:
StreamEx.ofKeys(names, "Donkey"::equals).findFirst().orElse(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();
}
假设我有一个名字、姓氏对的地图,我想在该地图中找到姓氏与特定值匹配的第一个条目的名字。 我们如何以 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);
}
提前致谢。
来自类似的 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());
}
然后你可以 select 第一个,如果你愿意的话。请记住 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;
}
给return一个默认值如果没有匹配,使用Optional#orElse
names.entrySet().stream()
.filter(e -> e.getValue().equals("Donkey"))
.map(Map.Entry::getKey)
.findFirst()
.orElse(null);
如果你不想使用第三方代码,@Misha 提供的解决方案是最好的解决方案。 My library has the special shortcut method ofKeys
对于这种情况,我发现这是很常见的任务:
StreamEx.ofKeys(names, "Donkey"::equals).findFirst().orElse(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();
}