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のストリームを作成し、それを別のストリームと連結しているので、これは本当にエレガントで無駄に感じられます。これを行うためのよりクリーンな方法はありますか?
2つのStreams
を作成せずにそれを行う方法を次に示しますが、気に入らない場合もあります。
Stream.Builder<String> builder = Stream.<String>builder().add(required);
for (String s : additional) {
builder.add(s);
}
Stream<String> allParams = builder.build();
残念ながら、Javaはかなり冗長になる可能性があります。しかし、それを軽減する別のオプションは、静的インポートを使用することです。私の意見では、すべてのメソッドはストリームに関連しているため、コードを明確にすることはできません。
Stream<String> allParams =
concat(of(required), of(additional));
構成されたストリームに問題はありません。これらのオブジェクトは、ソースデータのみを参照し、配列の内容などのデータをコピーしないため、軽量です。そのような軽量オブジェクトのコストは、実際のペイロードも非常に小さい場合にのみ関連する可能性があります。このようなシナリオは、特別な意味的に同等のオーバーロードで処理できます。
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
がライブラリではなくアプリケーションの一部である場合は、プロファイラーがそのパラメーター処理によってボトルネックが発生していることを通知しない限り、それらを追加しないでください。
Guavaを使用する場合は、Lists.asList(required, additional).stream()
を使用できます。このメソッドは、最小要件のイディオムで可変引数を緩和するために作成されました。
余談ですが、ライブラリは本当に便利だと思いますが、もちろんそれだけで追加するのは得策ではありません。 docs を確認し、それがあなたにとってより役立つかどうかを確認してください。