繁体   English   中英

使用接口进行流减少操作

[英]Stream reduce operation using interface

我有以下结构

public interface ICommon{
   ICommon add(ICommon other);
}

public class Foo implements ICommon{
    ...

    ICommon add(ICommon other){
        return new Bar().add(other);
    }

}

public class Bar implements ICommon{
    ...

    ICommon add(ICommon other){
        ...
    }

}

作为复合模式的一部分。

我想使用流减少操作,但是以某种方式我无法将类型推断强制给接口。 我正在用这个。

List<Foo> list;
list.stream().reduce( new Foo(), (a,b) -> a.add(b));

我收到一个错误,无法将ICommonFoo

我试图强制对参数进行强制转换,但没有成功。

这里的问题是您的List已用Foo进行了参数设置, ICommon由于add调用,您的缩减操作将使用ICommon进行了参数ICommon

尽管所有Foo都是ICommon ,但并非所有ICommon都将是Foo

最简单的方法是改为使用ICommon参数化List ,而无需更改(可见)代码中的任何其他内容。

就像是:

List<ICommon> list = [some list of Foos];
list.stream().reduce( new Foo(), (a,b) -> a.add(b));

找到了解决问题的办法。 还原操作具有签名

T reduce(T identity, BinaryOperator<T> accumulator);

我要做的只是投放到ICommon的信息流中

list.stream().map(x-> (ICommon) x).reduce( new Foo(), (a,b) -> a.add(b));

reduce的三个参数版本允许在执行reduce时更改元素类型:

list.stream().reduce(new Foo(), ICommon::add, ICommon::add);

而以相同的方法的引用在这里所使用的,第二个参数是函数( BiFunction )与(ICommon,Foo) -> ICommon签名,而第三个参数是函数( BinaryOperator )与(ICommon,ICommon) -> ICommon签名。

另一个选择是对现有List的类型进行类型安全的更改:

Collections.<ICommon>unmodifiableList(list).stream().reduce(new Foo(), ICommon::add);

由于不可变列表可以保证返回实际元素类型的超级类型的值,同时防止插入新元素,因此该包装器允许将元素类型更改为超级类型。 此外,由于流操作是只读操作,因此包装程序将stream()调用重定向到原始列表,只是将其作为超类型的流返回。 因此,直接使用list.stream()没有性能差异。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM