当输入整数没有输出时,使用Java 8流最佳方式来映射List<Integer>
?
简单地返回null?但现在我的输出列表大小将小于我的输入大小......
List<Integer> input = Arrays.asList(0,1,2,3);
List<Integer> output = input.stream()
.map(i -> {
Integer out = crazyFunction(i);
if(out == null || out.equals(0))
return null;
return Optional.of(out);
})
.collect(Collectors.toList());
答案 0 :(得分:46)
我不明白为什么你(以及所有的答案)让它如此复杂。您有映射操作和过滤操作。所以最简单的方法就是一个接一个地应用这些操作。除非您的方法已经返回Optional
,否则无需处理Optional
。
input.stream().map(i -> crazyFunction(i))
.filter(out -> out!=null && !out.equals(0))
.collect(Collectors.toList());
可以简化为
input.stream().map(context::crazyFunction)
.filter(out -> out!=null && !out.equals(0))
.collect(Collectors.toList());
但是你似乎有更多的理论问题,关于生成什么样的List
,一个是缺少值的占位符,另一个是与输入列表不同的大小。
简单的答案是:不生成列表。 List
本身不是目的,因此您应该考虑需要此类列表(或其内容)的操作,并将操作权应用为流的终端操作。然后你得到答案,因为操作决定是否应该过滤掉缺席值或用特殊值表示(以及必须具有的值)。
对于不同的操作,它可能是一个不同的答案......
答案 1 :(得分:29)
将map
来电替换为flatMap
。 map
操作为每个输入值生成一个输出值,而flatMap
操作为每个输入值生成任意数量的输出值 - 包括零。
最直接的方法可能就是更换支票:
List<Integer> output = input.stream()
.flatMap(i -> {
Integer out = crazyFunction(i);
if (out == null || out.equals(0))
return Stream.empty();
else
return Stream.of(out);
})
.collect(Collectors.toList());
进一步重构可能会更改crazyFunction
以使其返回Optional
(可能为OptionalInt
)。如果您从map
拨打电话,则结果为Stream<OptionalInt>
。然后,您需要flatMap
该流来删除空的选项:
List<Integer> output = input.stream()
.map(this::crazyFunctionReturningOptionalInt)
.flatMap(o -> o.isPresent() ? Stream.of(o.getAsInt()) : Stream.empty())
.collect(toList());
flatMap
的结果是Stream<Integer>
,其中列出了int
,但这是可以的,因为您要将它们发送到List
。如果您不打算将int
值设置为List
,则可以使用以下内容将Stream<OptionalInt>
转换为IntStream
:
flatMapToInt(o -> o.isPresent() ? IntStream.of(o.getAsInt()) : IntStream.empty())
有关处理选项流的进一步讨论,请参阅this question and its answers。
答案 2 :(得分:2)
@Martin Magakian回答的简单变体:
List<Integer> input = Arrays.asList(0,1,2,3);
List<Optional<Integer>> output =
input.stream()
.map(i -> crazyFunction(i)) // you can also use a method reference here
.map(Optional::ofNullable) // returns empty optional
// if original value is null
.map(optional -> optional.filter(out -> !out.equals(0))) // return empty optional
// if captured value is zero
.collect(Collectors.toList())
;
List<Integer> outputClean =
output.stream()
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList())
;
答案 3 :(得分:1)
您可以将输出包装到Optional中,该{{3}}可能包含也可能不包含非空值
输出:return Optional.of(out);
没有输出:return Optional.<Integer>empty();
你必须包装一个选项,因为一个数组不能包含任何空值。
List<Integer> input = Arrays.asList(0,1,2,3);
List<Option<Integer>> output = input.stream()
.map(i -> {
Integer out = crazyFunction(i);
if(out == null || out.equals(0))
return Optional.<Integer>empty();
return Optional.of(out);
})
.collect(Collectors.toList());
这将确保input.size() == output.size()
。
稍后您可以使用以下方法排除空的可选:
List<Integer> outputClean = output.stream()
.filter(Optional::isPresent)
.map(i -> {
return i.get();
})
.collect(Collectors.toList());