web-dev-qa-db-ja.com

Java 8ストリームと可変引数

Effective Java 2nd Edによると、varargsを許可しながら、コンパイル時に1つの要素が最小であることを強制するメソッドシグネチャを記述したい場合は、メソッドシグネチャを次のように記述します。

public void something(String required, String ... additional) {
    //... do what you want to do
}

これらのすべての要素をストリーミングしたい場合、私は次のようなことをしています:

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

特に1のストリームを作成し、それを別のストリームと連結しているので、これは本当にエレガントで無駄に感じられます。これを行うためのよりクリーンな方法はありますか?

12

2つのStreamsを作成せずにそれを行う方法を次に示しますが、気に入らない場合もあります。

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

Stream<String> allParams = builder.build();
6
Sleiman Jneidi

残念ながら、Javaはかなり冗長になる可能性があります。しかし、それを軽減する別のオプションは、静的インポートを使用することです。私の意見では、すべてのメソッドはストリームに関連しているため、コードを明確にすることはできません。

Stream<String> allParams =
    concat(of(required), of(additional));
2
user140547

構成されたストリームに問題はありません。これらのオブジェクトは、ソースデータのみを参照し、配列の内容などのデータをコピーしないため、軽量です。そのような軽量オブジェクトのコストは、実際のペイロードも非常に小さい場合にのみ関連する可能性があります。このようなシナリオは、特別な意味的に同等のオーバーロードで処理できます。

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
}

したがって、引数が1つだけの場合は、Streamインスタンスだけでなくvarargs配列も保存します(Stream.ofのオーバーロードと同様)。これは一般的なパターンです。たとえば、EnumSet.ofオーバーロードを参照してください。

ただし、多くの場合、これらの単純なオーバーロードでさえ不要であり、時期尚早の最適化と見なされる可能性があります(JREなどのライブラリは、アプリケーション開発者が必要に応じて追加することができないため、JREのようなライブラリによって提供されます)。 somethingがライブラリではなくアプリケーションの一部である場合は、プロファイラーがそのパラメーター処理によってボトルネックが発生していることを通知しない限り、それらを追加しないでください。

2
Holger

私の StreamEx または jOOλ のようなStream APIのサードパーティ拡張機能は、appendまたはprependのようなメソッドを提供します。きれいな方法:

// Using StreamEx
Stream<String> allParams = StreamEx.of(required).append(additional);
// Using jOOL
Stream<String> allParams = Seq.of(required).append(additional);
1
Tagir Valeev

Guavaを使用する場合は、Lists.asList(required, additional).stream()を使用できます。このメソッドは、最小要件のイディオムで可変引数を緩和するために作成されました。

余談ですが、ライブラリは本当に便利だと思いますが、もちろんそれだけで追加するのは得策ではありません。 docs を確認し、それがあなたにとってより役立つかどうかを確認してください。

1
andrepnh