在应用收集之前,如何从流中删除零元素?

发布于 2025-02-12 01:25:53 字数 541 浏览 1 评论 0原文

我的流函数有时会返回null,当我收集它们时如何删除该null返回?

versions.stream().map(vs->{
        if(vs.matches("^matched string$")) {
                ...
                return new VersionNumber(tmp[0], tmp[1], tmp[2]));
        }
        return null;
    }).flatMap(Optional::stream).collect(Collectors.toList());

对于此流函数,如果所有匹配均为false,则是指map()方法中的所有功能,它将上升nullpointException

如何使此流不引起异常,并且当所有元素均为null使其返回空列表或null

My stream function sometime returns null, when I do collect them How to delete that null return?

versions.stream().map(vs->{
        if(vs.matches("^matched string
quot;)) {
                ...
                return new VersionNumber(tmp[0], tmp[1], tmp[2]));
        }
        return null;
    }).flatMap(Optional::stream).collect(Collectors.toList());

For this stream functions, if all matched is false, I mean if all the function inside the map() method, it will rise NullPointException.

How to make this stream not rise an exception and when all elements are null make it to return an empty list or null?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

傲娇萝莉攻 2025-02-19 01:25:53

您可以后来过滤

versions.stream().map(vs->{
        if(vs.matches("^matched string$")) {
                ...
                return new VersionNumber(tmp[0], tmp[1], tmp[2]));
        }
        return null;
    }).filter(Objects::nonNull).flatMap(Optional::stream).collect(Collectors.toList());

,但这是更明智的过滤

versions.stream().filter(vs -> vs.matches("^matched string$"))
                 .map(vs->{
                           ...
                           return new VersionNumber(tmp[0], tmp[1], tmp[2]));
    }).flatMap(Optional::stream).collect(Collectors.toList());

You can filter afterward

versions.stream().map(vs->{
        if(vs.matches("^matched string
quot;)) {
                ...
                return new VersionNumber(tmp[0], tmp[1], tmp[2]));
        }
        return null;
    }).filter(Objects::nonNull).flatMap(Optional::stream).collect(Collectors.toList());

But that is wiser to filter the sooner

versions.stream().filter(vs -> vs.matches("^matched string
quot;))
                 .map(vs->{
                           ...
                           return new VersionNumber(tmp[0], tmp[1], tmp[2]));
    }).flatMap(Optional::stream).collect(Collectors.toList());
尬尬 2025-02-19 01:25:53

如果所有匹配都是错误的,我的意思是,如果所有函数在.map方法中,则它将上升nullpointException

因为您正在获得nullpointerexception,这意味着您的代码编译和编译代码跑步。因此,我假设map()操作中的“代码”不是您的实际代码选项。

flatmap(可选:: stream)仅当先前的map()产生类型可选< versionNumber>时,才不会导致汇编错误。

因此,我的建议很简单:永远不会返回 null 代替可选的。当可选对象可能是null时,它应该包含一个值或为空是完全错误的,但绝不应该是null

正如 @andy thomas 在评论中指出的那样,如果no 如果可选如果代码map()中的代码()真正在现场创建对象,例如new versionNumber(TMP [0],TMP [1],TMP [2]));。在这种情况下,将map()的结果与可选一起包装,将是对可选的滥用。返回versionNumber实例或null。然后应用一个过滤器:

    .map(vs -> {
            if (vs.matches("^matched string$")) {
            ...
            return new VersionNumber(tmp[0], tmp[1], tmp[2]);
        }
        return null;
    })
    .filter(Objects::nonNull)
    .collect(Collectors.toList());

您必须求助于可选的 ,如果您实际上是不是而不是创建version> versionnumber当您've显示了,但是,例如,如果某种条件是肉,请返回可选>的API调用。

    .map(vs -> {
        if (vs.matches("^matched string$")) {
            ...
            return getVersionNumber(tmp[0], tmp[1], tmp[2]); // method returing Optional<VersionNumber>
        }
        return Optional.empty();
    })
    .flatMap(Optional::stream)
    .collect(Collectors.toList());

在这种情况下,无需应用过滤。 optional.stream()在空的可选时调用时会产生一个空流。

if all matched is false, I mean if all the function in .map method, it will rise a NullPointException

Since you're getting a NullPointerException that means that your code compiles and running. Therefore, I assume that the "code" inside the map() operation isn't your actual code because we can't treat elements in the of Stream<VersionNumber> as optionals.

flatMap(Optional::stream) will not cause a compilation error only if preceding map() produces a result of type Optional<VersionNumber>.

Hence, my suggestion is simple: never return null in place of optional. It's completely wrong when an optional object might be null, it should either contain a value or be empty, but it should never be null.

And as @Andy Thomas has pointed out in the comment, there's no reason to utilize Optional if the code inside the map() really creates the object on the spot like new VersionNumber(tmp[0], tmp[1], tmp[2]));. In this case, wrapping the result of the map() with an Optional will be a misuse of optional. Return either VersionNumber instance or null. And then apply a filter:

    .map(vs -> {
            if (vs.matches("^matched string
quot;)) {
            ...
            return new VersionNumber(tmp[0], tmp[1], tmp[2]);
        }
        return null;
    })
    .filter(Objects::nonNull)
    .collect(Collectors.toList());

You have to resort to the usage of optional only if inside the map you're actually not creating VersionNumber as you've shown, but, for instance, making an API call which return an Optional<VersionNumber> if some condition is meat.

    .map(vs -> {
        if (vs.matches("^matched string
quot;)) {
            ...
            return getVersionNumber(tmp[0], tmp[1], tmp[2]); // method returing Optional<VersionNumber>
        }
        return Optional.empty();
    })
    .flatMap(Optional::stream)
    .collect(Collectors.toList());

In such a case, there's no need to apply filtering. Optional.stream() when invoked on an empty optional produces an empty stream.

十二 2025-02-19 01:25:53

从Java 16开始,还有 stream.mapmulti

返回由由多个元素替换该流的每个元素的结果的流,特别是 Zero 或更多元素。

(强调矿山)

使用此矿场,您的示例变为:

versions.stream().mapMulti((vs, consumer)->{
        if(vs.matches("^matched string$")) {
                ...
                consumer.accept(new VersionNumber(tmp[0], tmp[1], tmp[2]));
        }    
}).collect(Collectors.toList());

请注意,零值根本不是下游发射的,因此无需过滤或中间流以进行平面映射。


另一个例子:

record A(String name, long count) {}

public static void main(String[] args) {
    Stream.of(new A("apple", 1), new A("orange", 3), new A("banana", 0))
        .mapMulti((bucket, consumer) -> {
            for (int i = 0; i < bucket.count(); i++) {
                consumer.accept(bucket.name());
            }
        })
        .forEachOrdered(System.out::println);       
}

印刷:

apple
orange
orange
orange

3个橙子,但没有香蕉

As of java 16, there is also Stream.mapMulti:

Returns a stream consisting of the results of replacing each element of this stream with multiple elements, specifically zero or more elements.

(emphasis mine)

Using this, your example becomes:

versions.stream().mapMulti((vs, consumer)->{
        if(vs.matches("^matched string
quot;)) {
                ...
                consumer.accept(new VersionNumber(tmp[0], tmp[1], tmp[2]));
        }    
}).collect(Collectors.toList());

Note that the null values are not emitted downstream at all, so there is no need for filtering or intermediate streams for flat mapping.


Another example:

record A(String name, long count) {}

public static void main(String[] args) {
    Stream.of(new A("apple", 1), new A("orange", 3), new A("banana", 0))
        .mapMulti((bucket, consumer) -> {
            for (int i = 0; i < bucket.count(); i++) {
                consumer.accept(bucket.name());
            }
        })
        .forEachOrdered(System.out::println);       
}

Prints:

apple
orange
orange
orange

3 oranges, but no banana

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文