Stream.findFirst与Optional.of不同? [英] Stream.findFirst different than Optional.of?

查看:713
本文介绍了Stream.findFirst与Optional.of不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有两个课程和两个方法:

Lets say I have two classes and two methods:

class Scratch {
    private class A{}
    private class B extends A{}

    public Optional<A> getItems(List<String> items){
        return items.stream()
             .map(s -> new B())
             .findFirst();
    }

    public Optional<A> getItems2(List<String> items){
        return Optional.of(
            items.stream()
                 .map(s -> new B())
                 .findFirst()
                 .get()
        );
    }
}

为什么 getItems2 编译而 getItems 给出编译器错误

Why does getItems2 compile while getItems gives compiler error

incompatible types: java.util.Optional<Scratch.B> cannot be converted to java.util.Optional<Scratch.A>

所以,当我获取的价值时可选 findFirst 返回并再次用 Optional.of 如果直接使用 findFirst 的结果,编译器会识别继承但不会。

So when I get the value of the Optional returned by findFirst and wrap it again with Optional.of the compiler recognizes the inheritance but not if I use directly the result of findFirst.

推荐答案

可选< B> 不是的子类型< A> 。与其他编程语言不同,Java的泛型类型系统不知道只读类型或输出类型参数,因此它不理解可选< B> 仅提供 B 的实例,可以在需要 Optional< A> 的地方使用。

An Optional<B> is not a subtype of Optional<A>. Unlike other programming languages, Java’s generic type system does not know "read only types" or "output type parameters", so it doesn’t understand that Optional<B> only provides an instance of B and could work at places where an Optional<A> is required.

当我们写一个类似

Optional<A> o = Optional.of(new B());

Java的类型推断使用目标类型来确定我们想要

Java’s type inference uses the target type to determine that we want

Optional<A> o = Optional.<A>of(new B());

有效新B()可以在需要 A 的实例的情况下使用。

which is valid as new B() can be used where an instance of A is required.

这同样适用于

return Optional.of(
        items.stream()
             .map(s -> new B())
             .findFirst()
             .get()
    );

其中方法声明的返回类型用于推断的类型参数Optional.of 调用并传递 get()的结果, B的实例 ,其中 A 是必需的。

where the method’s declared return type is used to infer the type arguments to the Optional.of invocation and passing the result of get(), an instance of B, where A is required, is valid.

不幸的是,这种目标类型推断无法通过链式调用工作,所以对于

Unfortunately, this target type inference doesn’t work through chained invocations, so for

return items.stream()
     .map(s -> new B())
     .findFirst();

它不用于地图来电。因此,对于 map 调用,类型推断使用 new B()的类型,其结果类型将为流< B个。第二个问题是 findFirst()不是通用的,在上调用它< T> 总是产生一个可选< T> (并且Java的泛型不允许声明类型变量,如< R super T> ,所以甚至不可能在此处生成可选< R> 并带有所需的类型。)

it is not used for the map call. So for the map call, the type inference uses the type of new B() and its result type will be Stream<B>. The second problem is that findFirst() is not generic, calling it on a Stream<T> invariably produces a Optional<T> (and Java’s generics does not allow to declare a type variable like <R super T>, so it is not even possible to produce an Optional<R> with the desired type here).

→解决方案是为地图提供显式类型调用:

public Optional<A> getItems(List<String> items){
    return items.stream()
         .<A>map(s -> new B())
         .findFirst();
}

为了完整性,如上所述, findFirst() 不是通用的,因此不能使用目标类型。链接允许类型更改的通用方法也可以解决问题:

Just for completeness, as said, findFirst() is not generic and hence, can’t use the target type. Chaining a generic method allowing a type change would also fix the problem:

public Optional<A> getItems(List<String> items){
    return items.stream()
         .map(s -> new B())
         .findFirst()
         .map(Function.identity());
}

但我建议使用为<$ c提供显式类型的解决方案$ c> map 调用。

这篇关于Stream.findFirst与Optional.of不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆