从 Java 8 映射操作返回空元素

2022-09-01 04:04:47

使用Java 8流,当您没有输入整数的输出时,映射的最佳方法是什么?List<Integer>

只需返回空值?但是现在我的输出列表大小将小于我的输入大小...

    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());

答案 1

我不明白为什么你(和所有答案)让它变得如此复杂。您有一个映射操作和一个筛选操作。因此,最简单的方法是一个接一个地应用这些操作。除非您的方法已经返回 一个 ,否则无需处理 。OptionalOptional

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

简单的答案是:不要生成列表。A 本身不是目的,因此您应该考虑需要哪种操作来执行此列表(或其内容),并将该操作作为流的终端操作。然后你有你的答案,因为操作决定了是应该过滤掉缺失的值还是用一个特殊值(以及必须是什么值)来表示。List

对于不同的操作,这可能是一个不同的答案...


答案 2

将呼叫替换为 。该操作为每个输入值生成一个输出值,而该操作为每个输入值生成任意数量的输出值 - 包括零。mapflatMapmapflatMap

最直接的方法可能是像这样替换检查:

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());

进一步的重构可以更改为让它返回一个(可能是)。如果从 调用它,则结果为 。然后,您需要该流来删除空的可选选项:crazyFunctionOptionalOptionalIntmapStream<OptionalInt>flatMap

List<Integer> output = input.stream()
    .map(this::crazyFunctionReturningOptionalInt)
    .flatMap(o -> o.isPresent() ? Stream.of(o.getAsInt()) : Stream.empty())
    .collect(toList());

的结果是哪个框向上的 s,但这没关系,因为您将将它们发送到 .如果您不打算将这些值装箱到 中,则可以使用以下方法将 转换为 a:flatMapStream<Integer>intListintListStream<OptionalInt>IntStream

flatMapToInt(o -> o.isPresent() ? IntStream.of(o.getAsInt()) : IntStream.empty())

有关处理可选选项流的进一步讨论,请参阅此问题及其答案


推荐