【发布时间】:2015-06-02 23:37:10
【问题描述】:
假设我有一个名字、姓氏对的映射,并且我想找到该映射中第一个具有与某个值匹配的姓氏的条目的名字。 我们如何以 java 8 的方式做到这一点。
在下面的测试用例示例中,我提出了两种方法。
但是第一个(寻找姓氏为“驴”的第一个人的名字)将抛出 java.util.NoSuchElementException: No value present so it is not safe。
第二个有效,但它不仅更难阅读,而且有点不太实用。
只是想知道这里是否有人会建议我使用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);
}
提前谢谢你。
【问题讨论】:
-
显然使用双向地图会更有效。
-
嗨,patryk。我完全同意你的看法。这就是我发布问题的原因。你能提供解决方案吗?
-
对我来说,有些气味来自于使用
null。发布的答案都提供了null,因为这就是您所要求的。但是既然你已经购买了Optional,为什么还要使用null?将keyOfTheFirst设为Optional<String>并执行assertTrue(keyOfTheFirst.isEmpty())或其他。 -
@Stuart。当然使用
java.util.Optional是自然的方式,但这不是我想要的。我真正想要的是拥有一个纯功能解决方案,而不需要任何额外的检查/迭代等。这更像是一个理论问题“java 8 可以做到吗?”,因为我找不到我自己把答案贴在这里而不是断定它不能。单元测试只是为了帮助发帖者轻松练习他们的解决方案,而不是别的。 -
@Julian 够了。我在回应上面的评论,“这段代码有味道。糟糕的设计。”该评论可能是真的,但它并不是特别有用。虽然它与您所关注的问题没有直接关系,但我确实发现代码中的一个问题是它使用了
null,所以我建议了一个避免null的替代方案。
标签: java lambda java-8 java-stream optional