Ned*_*igg 32 java java-8 java-stream
我在这个函数式编程和流程方面有点绿色,但我知道的一点点非常有用!
我已经多次出现这种情况了:
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
}
Run Code Online (Sandbox Code Playgroud)
我真正想要的是:
Optional<SomeProperty> universalCommonProperty = someList.stream()
.map(obj -> obj.getSomeProperty())
.distinct()
.collect(Collectors.singleOrEmpty());
Run Code Online (Sandbox Code Playgroud)
我认为singleOrEmpty
除了与之相结合之外,这个东西在其他情况下也很有用distinct
.当我是一个超级n00b时,我花了很多时间重新发明Java Collections Framework,因为我不知道它在那里,所以我不想重复我的错误.Java是否有一个很好的方法来做这singleOrEmpty
件事?我错误地制定了它吗?
谢谢!
编辑:这是distinct
案例的一些示例数据.如果您忽略该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()
Run Code Online (Sandbox Code Playgroud)
当我搞砸了我的类型或遗留代码时,我发现我需要这个.很高兴能够快速说出"此集合的所有元素共享此属性,所以现在我可以使用此共享属性执行某些操作." 另一个例子是当用户多选一些不同的元素时,你正试图看看你能做什么(如果有的话)对所有这些元素都有效.
编辑2:对不起,如果我的例子有误导性.关键是singleOrEmpty.我经常发现我把它distinct
放在前面,但它可以很容易地成为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)
Run Code Online (Sandbox Code Playgroud)
EDIT3:我认为我通过激励singleOrEmpty而不仅仅是单独要求它而搞砸了.
Optional<Int> value = someList.stream().collect(Collectors.singleOrEmpty())
[] -> Optional.empty()
[1] -> Optional.of(1)
[1, 1] -> Optional.empty()
Run Code Online (Sandbox Code Playgroud)
Mis*_*sha 19
这将产生创建集合的开销,但它很简单并且即使您首先忘记distinct()流也能正常工作.
static<T> Collector<T,?,Optional<T>> singleOrEmpty() {
return Collectors.collectingAndThen(
Collectors.toSet(),
set -> set.size() == 1
? set.stream().findAny()
: Optional.empty()
);
}
Run Code Online (Sandbox Code Playgroud)
Tho*_*lut 13
"Hacky"解决方案仅评估前两个元素:
.limit(2)
.map(Optional::ofNullable)
.reduce(Optional.empty(),
(a, b) -> a.isPresent() ^ b.isPresent() ? b : Optional.empty());
Run Code Online (Sandbox Code Playgroud)
一些基本解释:
单个元素 [1] - >映射到[Optional(1)] - > reduce do
"Empty XOR Present" yields Optional(1)
Run Code Online (Sandbox Code Playgroud)
=可选(1)
两个元素 [1,2] - >映射到[Optional(1),Optional(2)] - > reduce do:
"Empty XOR Present" yields Optional(1)
"Optional(1) XOR Optional(2)" yields Optional.Empty
Run Code Online (Sandbox Code Playgroud)
= 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)));
}
Run Code Online (Sandbox Code Playgroud)
感谢Ned(OP)贡献了XOR理念和上述测试用例!
如果你不介意使用Guava,你可以用你的代码包装Iterables.getOnlyElement
,所以它看起来像这样:
SomeProperty distinctProperty = Iterables.getOnlyElement(
someList.stream()
.map(obj -> obj.getSomeProperty())
.distinct()
.collect(Collectors.toList()));
Run Code Online (Sandbox Code Playgroud)
IllegalArgumentException
如果有多个值或没有值,则会引发,也有一个默认值的版本.
为此构建收集器的更简洁方法如下:
Collectors.reducing((a, b) -> null);
Run Code Online (Sandbox Code Playgroud)
reduce collection将存储第一个值,然后在连续传递时,将当前运行值和新值传递给lambda表达式.此时,始终可以返回null,因为不会使用第一个值调用null,这将仅存储.
将其插入代码中:
Optional<SomeProperty> universalCommonProperty = someList.stream()
.map(obj -> obj.getSomeProperty())
.distinct()
.collect(Collectors.reducing((a, b) -> null));
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
24285 次 |
最近记录: |