我对这种函数式编程和流技术有点陌生,但是我所知道的一点却非常有用!
我遇到过几次这种情况:
List<SomeProperty> distinctProperties = someList.stream() .map(obj -> obj.getSomeProperty()) .distinct() .collect(Collectors.toList()); if (distinctProperties.size() == 1) { SomeProperty commonProperty = distinctProperties.get(0); // take some action knowing that all share this common property }
我真正想要的是:
Optional<SomeProperty> universalCommonProperty = someList.stream() .map(obj -> obj.getSomeProperty()) .distinct() .collect(Collectors.singleOrEmpty());
我认为,singleOrEmpty除了与结合使用外,该东西在其他情况下也可能有用distinct。当我成为超级n00b时,我花了很多时间重新发明Java Collections Framework,因为我不知道它在那里,所以我试图不重蹈覆辙。Java是否提供了执行此操作的好方法singleOrEmpty?我说错了吗?
singleOrEmpty
distinct
谢谢!
编辑:这是distinct案例的一些示例数据。如果您忽略该map步骤:
map
Optional<SomeProperty> universalCommonProperty = someList.stream() .map(obj -> obj.getSomeProperty()) .distinct() .collect(Collectors.singleOrEmpty()); [] -> Optional.empty() [1] -> Optional.of(1) [1, 1] -> Optional.of(1) [2, 2] -> Optional.of(2) [1, 2] -> Optional.empty()
当我搞砸我的类型或有旧代码时,我发现我需要这个。能够快速地说出“此集合的所有元素共享此属性,这真是太好了,因此现在我可以使用此共享属性采取一些措施。” 另一个示例是,当用户多重选择一些不同的元素,而您试图查看可以做的事情(如果有的话)对所有元素都有效。
EDIT2:对不起,如果我的例子有误导性。关键是 singleOrEmpty 。我通常会发现我放在distinct前面,但也可以很容易地成为filter其他类型的对象。
filter
Optional<SomeProperty> loneSpecialItem = someList.stream() .filter(obj -> obj.isSpecial()) .collect(Collectors.singleOrEmpty()); [special] -> Optional.of(special) [special, special] -> Optional.empty() [not] -> Optional.empty() [not, special] -> Optional.of(special) [not, special, not] -> Optional.of(special)
EDIT3:我想通过激励 singleOrEmpty 而不是 单独 要求它来搞砸。
Optional<Int> value = someList.stream().collect(Collectors.singleOrEmpty()) [] -> Optional.empty() [1] -> Optional.of(1) [1, 1] -> Optional.empty()
仅评估前两个元素的“ Hacky”解决方案:
.limit(2) .map(Optional::ofNullable) .reduce(Optional.empty(), (a, b) -> a.isPresent() ^ b.isPresent() ? b : Optional.empty());
一些基本的解释:
单个元素 [1]->映射到[Optional(1)]-> reduce
"Empty XOR Present" yields Optional(1)
=可选(1)
两个元素 [1,2]->映射到[Optional(1),Optional(2)]-> reduce可以:
"Empty XOR Present" yields Optional(1) "Optional(1) XOR Optional(2)" yields Optional.Empty
=可选。空
这是完整的测试用例:
public static <T> Optional<T> singleOrEmpty(Stream<T> stream) { return stream.limit(2) .map(Optional::ofNullable) .reduce(Optional.empty(), (a, b) -> a.isPresent() ^ b.isPresent() ? b : Optional.empty()); } @Test public void test() { testCase(Optional.empty()); testCase(Optional.of(1), 1); testCase(Optional.empty(), 1, 1); testCase(Optional.empty(), 1, 1, 1); } private void testCase(Optional<Integer> expected, Integer... values) { Assert.assertEquals(expected, singleOrEmpty(Arrays.stream(values))); }
对于贡献XOR想法和上述测试用例的Ned(OP)表示感谢!