【问题标题】:<R> Stream<R> map(Function<? super T, ? extends R> mapper) Stream<R> Stream<R> map(Function<? super T, ? extends R> mapper) Stream
【发布时间】:2018-12-13 06:11:03
【问题描述】:

我在看流接口,发现了这个方法:

 <R> Stream<R> map(Function<? super T, ? extends R> mapper);

我找不到任何理由为什么“?扩展 R”而不是 R:

 <R> Stream<R> map(Function<? super T, R> mapper);

如果我像上面那样做会有什么不同?不是“?”是我通过的 R 变量吗?它会扩展 R 我找不到它的原因。

【问题讨论】:

  • 这也太支持多态和动态绑定了。

标签: java java-stream


【解决方案1】:

它使用? extends R 允许将map 采用的函数声明为返回R 的子类型

例如,给定这个流:

Stream<Number> numberStream = Stream.of(1, 2L);

在下面的map调用中,RNumber,但函数的类型是Function&lt;Number, Integer&gt;

Function<Number, Integer> function = n -> Integer.valueOf(n.intValue());
Stream<Number> numberStream2 = numberStream.map(function); //would have failed

如果不采用? extends R,则function 将是无效参数(需要Function&lt;Number, Number&gt;

【讨论】:

  • @earnest_k R 这是整数扩展的东西吗?这不仅仅是数字。只是作为“?扩展 R”的通用答案。感谢您的回答
  • @MohammadKarmi 此答案中有两个R。对于Function&lt;Number, Integer&gt;RInteger。对于numberStream.map(function)RNumber
  • 正确。但我可以使用整数扩展的任何东西:Stream&lt;Serliazable&gt; numberStream2 = numberStream.map(function); 所以 R 可以是这里整数扩展的任何东西。这就是我想说的。在你的例子中是数字谢谢:)
  • 没有。它必须是NumberNumber 的子类型。因此,您不能使用例如Function&lt;Number, Object&gt;Integer 扩展Object,但这将是无效的,因为Object 不是Number 的子类型)。如果您的意思是任何扩展 Integer 的东西,那么是的 - 但 Integer 是一个不好的例子,因为我们没有可以用来说明它的子类型 :-)
  • 不,我的意思是,R 是这里的整数的超级。这就是为什么这项工作:Stream&lt;Serliazable&gt; numberStream2 = numberStream.map(function); R 这里是可序列化的,如果我错了请纠正我
【解决方案2】:

? extends R 表示您可以传递其类派生自 R 的对象,也就是 R 的子类。

所以 map 函数可以产生RR's subclass 作为结果。这是合理的。

例如,如果我们有这些类: Animal, Groose (extends Animal), Egg Function&lt;Egg, Groose&gt; hatching

你可以写这个代码:

List<Egg> eggs = getEggs();
List<Animal> myPets = eggs.stream().map(hatching)....

您可以看到您的map 函数需要Animal 类型(R),但您的映射器返回Groose 类型(即? extends R)。如果map 函数写为&lt;R&gt; Stream&lt;R&gt; map(Function&lt;? super T, R&gt; mapper);,则必须添加另一个从GrooseAnimal 的转换。

可以参考this answer了解&lt;? extends T&gt;

【讨论】:

    【解决方案3】:

    在 Java 中泛型是不变的,这意味着即使 S 扩展了 P,下面的代码也会抛出编译错误 -

    List<S> list1 = neww ArrayList<>();
    List<P> list2 = list1 ; // compile error
    

    但如果你有 Listthen 你可以做以下事情:

    List<S> list1 = neww ArrayList<>();
    List<? extends P> list2 = list1 ;
    

    【讨论】:

      猜你喜欢
      • 2021-01-14
      • 2017-07-06
      • 1970-01-01
      • 1970-01-01
      • 2020-07-05
      • 2019-11-08
      • 2017-10-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多