【问题标题】:How can I create a Stream<String[]> with only one element with Stream.of?如何使用 Stream.of 创建一个只有一个元素的 Stream<String[]>?
【发布时间】:2018-07-15 11:43:44
【问题描述】:

使用Stream.of创建泛型流很方便,但是如果我想创建一个只有一个元素的Stream&lt;String[]&gt;呢?

假设我有:

String[] tropicalFruits = new String[] {"pineapple", "banana", "mango"};
String[] fruits = new String[] {"melon", "peach", "apple"};

然后Stream.of(tropicalFruits, fruits) 产生两个元素的Stream&lt;String[]&gt;。如何为单个元素的流实现相同的效果?如果我尝试:

Stream<String[]> fruityStream = Stream.of(tropicalFruits);

我明白了:

错误:不兼容的类型:推理变量T 不兼容 界限
等式约束:java.lang.String[]
下界:java.lang.String

Stream<String[]> fruityStream = Stream.of(fruits);
                                 ^---------------^

我已经用谷歌搜索过这个并在 SO 中搜索过,但我什么也没得到。在我看来,这不是一个非常不寻常或深奥的问题,所以我没有得到任何答案(或者我没有使用正确的关键字搜索)有点令人惊讶。

【问题讨论】:

  • 你可以使用 Stream.Builder
  • 另一个问题的正确答案。 :)
  • 为什么不同? Stream&lt;String[]&gt; stream = Stream.&lt;String[]&gt;builder().add(new String[] {"a", "b"}).build(); 也是正确的解决方案,尽管它不像 accepted 答案那么简单。 @阿尔夫
  • 你的解决方案没有使用Stream.of,这才是重点。

标签: java java-8 java-stream variadic-functions type-inference


【解决方案1】:

通过使用单个T[] 调用Stream#of,Java 默认为vararg factory method,创建Stream&lt;T&gt; 而不是Stream&lt;T[]&gt;。要创建具有单个元素的 Stream&lt;T[]&gt;,您可以创建具有多个元素的 Stream&lt;T[]&gt; 并调用 limit(1),或者对第二个元素使用虚拟数组:

Stream<String[]> stream = Stream.of(tropicalFruits, fruits).limit(1);

Stream<String[]> stream = Stream.of(tropicalFruits, new String[] {});

【讨论】:

    【解决方案2】:

    这个Stream&lt;String[]&gt; fruittyStream = Stream.of(tropicalFruits);

    调用Stream.of的var-arg方法。

    我能想到这个解决方法:

    List<String> list = Arrays.asList("one");
    Stream.of(list)
          .map(x -> x.toArray(new String[1]));
    

    或者您可以稍微不同地调用 var-args 方法:

     Stream.of(tropicalFruits, null)
           .filter(Objects::nonNull)
           .forEach(x -> System.out.println(Arrays.toString(x)));
    

    【讨论】:

      【解决方案3】:

      解决方案

      Stream<String[]> stream = Stream.<String[]>of(tropicalFruits);
      

      Stream<String[]> stream = Stream.of(new String[][]{tropicalFruits});
      

      说明

      要生成Stream&lt;T&gt;Stream.of 需要TT...
      T[] 参数完全适用于第二个签名。
      因此,传递String[] 会调用Stream.of(String...) 版本。

      要改变这种行为,我们需要提供一些关于T 的额外信息(1) 或更清楚地定义它(=明确)(2)。

      我想到了两个想法:

      1. 明确指定方法的类型参数以使用第一个签名。
        Stream.&lt;String[]&gt;of(new String[]{}) 将生成 Stream&lt;String[]&gt;
      2. T[] 值包装在T[][] 数组中以使用第二个签名。
        Stream.of(new String[][]{}) 将生成Stream&lt;String[]&gt;

      【讨论】:

      • 哦,添加更多类型信息真是太棒了!你应该解释一下我猜的第一个:)
      • 比我的答案更好!第一个看起来像是利用了可变参数,这太棒了。
      • 我喜欢 Jacob 和 Eugene 的其他两个答案,但我认为第二种解决方案是最正确的,因为它不需要创建任何额外的数组或列表。
      • List.of(E...) method's javadoc 中,API 说明了这种情况:此方法还接受单个数组作为参数。结果列表的元素类型将是数组的组件类型,列表的大小将等于数组的长度。要创建包含单个元素的列表,即数组,请执行以下操作: String[] array = ... ; List&lt;String[]&gt; list = List.&lt;String[]&gt;of(array);。我认为这个 API 说明也应该添加到 Stream.of(E...) 方法的文档中。
      • @FedericoPeraltaSchaffner 这很有趣,通常添加更多类型信息的工作原理是通过这种方式推断目标;但这里实际上是为了选择重载方法。很好的评论!
      猜你喜欢
      • 2021-12-19
      • 2012-10-04
      • 1970-01-01
      • 2019-10-12
      • 2016-06-18
      • 2015-01-23
      • 2018-09-17
      相关资源
      最近更新 更多