Java 8流和varargs

Pau*_*ker 10 java variadic-functions java-8 java-stream

根据Effective Java 2nd Ed,当你想编写一个允许varargs的方法签名但仍然强制你在编译时只有一个元素时,你应该这样编写方法签名:

public void something(String required, String ... additional) {
    //... do what you want to do
}
Run Code Online (Sandbox Code Playgroud)

如果我想要传输所有这些元素,我一直在做这样的事情:

public void something(String required, String ... additional) {
    Stream<String> allParams =
        Stream.concat(Stream.of(required), Stream.of(additional));
    //... do what you want to do
}
Run Code Online (Sandbox Code Playgroud)

这感觉非常不优雅和浪费,特别是因为我正在创建一个1流并将其与另一个连接.有更清洁的方法吗?

Sle*_*idi 6

这是一种不用创建两种方法就可以做到的方法Streams,尽管你可能不喜欢它.

Stream.Builder<String> builder = Stream.<String>builder().add(required);
for (String s : additional) {
  builder.add(s);
}

Stream<String> allParams = builder.build();
Run Code Online (Sandbox Code Playgroud)

  • 您还可以将 for-loop 替换为 `Stream.of(additional).forEach(builder);` (2认同)

Hol*_*ger 6

组合流没有任何问题。这些对象是轻量级的,因为它们只引用源数据,而不像数组内容那样复制数据。如果实际有效载荷也非常小,这种轻量级物体的成本可能才有意义。这些场景可以用专门的、语义上等效的重载来处理:

public void something(String required, String ... additional) {
    somethingImpl(Stream.concat(Stream.of(required), Stream.of(additional)));
}
public void something(String required) {
    somethingImpl(Stream.of(required));
}
public void something(String required, String second) {
    somethingImpl(Stream.of(required, second));
}
private void somethingImpl(Stream<String> allParams) {
    //... do what you want to do
}
Run Code Online (Sandbox Code Playgroud)

因此,在只有一个参数的情况下,您不仅要保存Stream实例,还要保存varargs 数组(类似于Stream.of的重载)。这是一种常见的模式,例如参见EnumSet.of重载。

然而,在很多情况下,即使这些简单的重载也不是必需的,并且可能被认为是过早优化(像 JRE 这样的库提供了它们,否则应用程序开发人员在需要时不可能添加它们)。如果something是应用程序而不是库的一部分,则不应添加它们,除非分析器告诉您该参数处理导致瓶颈。