【问题标题】:Java method signatures: Stream versus Collection versus var-argJava 方法签名:Stream 与 Collection 与 var-arg
【发布时间】:2017-01-02 14:11:03
【问题描述】:

对于 Java 8 Lambda/Closure,var-arg 方法签名是否有通用的最佳方法?

在将方法与单个对象作为参数或对象集合一起使用的情况下,我看到了三个选项来实现这一点:

 private void optionOneVararg(String... params) { ... }
 private void optionTwoCollection(Collection<String> params) { ... }
 private void optionThreeStream(Stream<String> params) { ... }

显然是用String类作为例子。

对此是否有普遍有效的“最佳实践”方法? vararg 方法生成了 Java 7 之前最流畅的代码。使用流时感觉很笨拙。

我希望能够在方法内部和调用它的外部使用 lambda 的便利性。此外,我想将包装/胶水代码(例如Collections.singletonList(element)Arrays.asList(element))保持在最低限度,并避免使用Collection myCollection = stream.collect(...),后跟myCollection.stream()

【问题讨论】:

  • 您不喜欢 vararg 选项的哪些方面?
  • 关于 var-args 主题,您可能想看看 this question
  • @assylias 当我对流使用操作(例如过滤器),然后将结果传递给我的函数,然后对该参数使用更多流操作时,可变参数数组需要收集之前的第一个流它可以交给函数。
  • 为什么不用不同的参数选项重载方法呢?就像 Java API 中的许多方法一样?

标签: java lambda java-8 java-stream


【解决方案1】:

您仍然可以通过调用 Stream.of(String...) 在方法中使用 Stream API 和 lambda。在这种情况下,您可以使用可变参数保留签名:

private void optionVarArgs(String... params) {
   Stream.of(params)...
   ...
}

【讨论】:

  • 好提示。但是调用方呢?这看起来真的很难看:stream.collect(Collectors.toList()).toArray(new String[0])
  • @SebastianH stream.toArray(String[]::new)
【解决方案2】:

感谢 AR.3 的回答,我意识到保留 Stream 作为参数在性能和美观方面都更胜一筹:

private void callOptionThreeFromStream() {
    List<String> foo = Arrays.asList(new String[] { "a", "b", "c" });
    Stream<String> stream = foo.stream();
    // use stream here
    optionThreeStream(stream);
}
private void callOptionThreeFromObject() {
    String bar = "a";
    optionThreeStream(Stream.of(bar)); //very simple conversion
}
private void optionThreeStream(Stream<String> params) {
    // use the same stream (and possibly profit from optimization)
}

使用可变参数会导致更多开销(至少在美学上):

private void callOptionOneFromStream() {
    List<String> foo = Arrays.asList(new String[] { "a", "b", "c" });
    Stream<String> stream = foo.stream();
    // use stream here
    optionOneVararg(stream.toArray(String[]::new)); //still clumsy
}
private void callOptionOneFromObject() {
    String bar = "a";
    optionOneVararg(bar); //but optimal here
}
private void optionOneVararg(String... params) {
    Stream<String> stream = Stream.of(params);
    // use the new stream on the newly created array
}

为了完整起见:

private void callOptionTwoFromStream() {
    List<String> foo = Arrays.asList(new String[] { "a", "b", "c" });
    Stream<String> stream = foo.stream();
    // use stream here
    optionTwoCollection(stream.collect(Collectors.toList())); //clumsy
}
private void callOptionTwoFromObject() {
    String bar = "a";
    optionTwoCollection(Collections.singletonList(bar)); //clumsy
}
private void optionTwoCollection(Collection<String> params) {
    Stream<String> stream = params.stream();
    // use the new stream on the newly created collection
}

我个人的结论:私有方法使用Stream。在公共 API 方法中保留 var-arg 或 Collections 可能更适合隐藏内部技术细节。

Stream.of 使用 var-arg 参数同时覆盖数组和单个对象,这是一个很好的细节。

【讨论】:

  • Stream.of() 不使用可变参数来覆盖单个对象。 of() 方法被重载。见:stackoverflow.com/questions/35802272/…
  • 很好的收获!谢谢。这并不是说我关心我的代码中的那种微优化,但你的问题读得很好。它还提供了另一个参数,可以在可用时将流移交给内部函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-20
  • 2018-01-15
  • 1970-01-01
  • 1970-01-01
  • 2020-04-30
相关资源
最近更新 更多