【问题标题】:transform List<Staging<Importable>> to List<Staging<ImportableImpl>> with java 8 stream使用 java 8 流将 List<Staging<Importable>> 转换为 List<Staging<ImportableImpl>>
【发布时间】:2016-12-02 16:01:44
【问题描述】:

假设我有一个名为Importable 的接口,它有多个实现,其中一个是ImportableImpl

我有一个类 Staging 的列表,它有一个泛型类型:Importable

通过 java 8 流,我想转换列表:

List<Staging<Importable>> list1

到一个列表:

List<Staging<ImportableImpl>> list2

我已经确定列表list1Staging&lt;ImportableImpl&gt; 的列表,因此不会出现ClassCastException。 不知道java是否授权这种泛型类型的转换。

我想尝试这样的事情:

list1.stream()
   .map(Staging::getImportable) // retrieve generic type
   .map(ImportableImpl.class::cast)
   .collect(Collectors.toList())

但是有了这个我会得到一个List&lt;ImportableImpl&gt;而不是List&lt;Staging&lt;ImportableImpl&gt;&gt;

【问题讨论】:

  • 如何创建Staging 对象?
  • 为什么需要这样做?也许您应该在界面中添加更多方法。

标签: java generics java-8 java-stream


【解决方案1】:

我真的不知道您尝试的目的是什么,但是无论第一个列表中的内容如何,​​都不允许您将List&lt;Staging&lt;Importable&gt;&gt; 转换为List&lt;Staging&lt;ImportableImpl&gt;&gt;。这些类型是不可转换的。

唯一合理的方法是:

@SuppressWarnings("unchecked") // if you are sure that all elements are ImportableImpl
list.stream().map(i -> (Staging<ImportableImpl>) i).collect(Collectors.toList());

list 的类型是 List&lt;Staging&lt;? extends Importable&gt;&gt;,而不是 List&lt;Staging&lt;Importable&gt;&gt;


当然可以用方法引用来写:

list.stream().map(Staging.class::<ImportableImpl>cast).collect(Collectors.toList());

【讨论】:

    【解决方案2】:

    在我看来,您必须创建一个新的暂存对象...

    此答案假设您可以使用new Staging&lt;&gt;(thing) 创建一个Staging 对象。这是你需要的吗?

    list1.stream()
       .map(s -> new Staging<ImportableImpl>(s.getImportable()))
       .collect(Collectors.toList())
    

    【讨论】:

    • 这是我选择的解决方案,但我想知道是否有办法在不创建新对象的情况下做到这一点。必须使用此解决方案重新设置暂存的所有其他字段。
    • @louisamoros 如果您确定暂存对象包含ImportableImpls,您可以进行不安全的强制转换,例如.map(s -&gt; (Staging&lt;ImportableImpl&gt;) ((Staging) s)))
    • @louisamoros 我同意其他一些 cmets,但这样做有点讨厌
    【解决方案3】:

    如果我做对了,那么您基本上只是想表达您的list1 实际上已经是List&lt;Staging&lt;ImportableImpl&gt;&gt; 类型的列表。从而抛弃了你的接口Importable提供的抽象。

    在运行时不存在任何通用类型,您应该能够只转换List&lt;Staging&lt;ImportableImpl&gt;&gt; list2 = (List) list1。这是一个未经检查的强制转换(使用原始形式作为中间体),并将消除类型系统提供的一些安全性。如果有人将Staging&lt;AnotherImportableImpl&gt; 类型的对象添加到list1,它可能会中断。 使用像流这样的花哨的构造并不会改变这种情况。基本上你只是想告诉编译器你确定你知道一些它不能检查的东西。

    【讨论】:

      猜你喜欢
      • 2019-12-06
      • 2016-11-02
      • 1970-01-01
      • 2018-02-15
      • 2021-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-31
      相关资源
      最近更新 更多