ある値からある値への連続した値でList<Integer>
、、またはおそらくまたは Integer[]
を生成するための短くて甘い方法はありますか?int[]
start
end
つまり、次の1より短いが、1と同等です。
void List<Integer> makeSequence(int begin, int end) {
List<Integer> ret = new ArrayList<>(end - begin + 1);
for (int i=begin; i<=end; i++) {
ret.add(i);
}
return ret;
}
グアバの使用は問題ありません。
アップデート:
パフォーマンス分析
この質問は、ネイティブJava 8とサードパーティライブラリの両方を使用していくつかの良い回答を受け取ったので、すべてのソリューションのパフォーマンスをテストすると思いました。
[1..10]
最初のテストは、次の方法を使用して10個の要素のリストを作成することをテストするだけです。
- classicArrayList:上記の私の質問のコード(そして本質的にadarshrの答えと同じ)。
- eclipseCollections: EclipseCollections8.0を使用した以下のDonaldの回答に示されているコード。
- guavaRange:以下のdavebの回答に示されているコード。技術的には、これは作成されません
List<Integer>
が、むしろContiguousSet<Integer>
-を作成しますが、順番に実装さIterable<Integer>
れるため、ほとんどの場合、私の目的で機能します。 - intStreamRange:以下のVladimirの回答
IntStream.rangeClosed()
に示されているコードで、Java8で導入された-を使用しています。 - streamIterate :以下のCatalinの回答に示されているコードで、 Java8
IntStream
で導入された機能も使用しています。
サイズ10のリストを使用した上記のすべてについて、1秒あたりのキロ操作数の結果を次に示します(数値が大きいほど良い)。
...サイズ10,000のリストの場合:
その最後のグラフは正しいです-EclipseとGuava以外のソリューションは遅すぎて、単一のピクセルバーを取得することさえできません!高速ソリューションは、他のソリューションよりも10,000〜20,000倍高速です。
もちろん、ここで起こっていることは、グアバとエクリプスのソリューションは実際にはいかなる種類の10,000要素リストも具体化しないということです-それらは開始と終了点の周りの単なる固定サイズのラッパーです。各要素は、反復中に必要に応じて作成されます。このテストでは実際には反復しないため、コストは繰り延べられます。他のすべてのソリューションは、実際にはメモリ内の完全なリストを具体化し、作成のみのベンチマークで高額を支払います。
もう少し現実的なことをして、すべての整数を繰り返し、それらを合計してみましょう。したがって、IntStream.rangeClosed
バリアントの場合、ベンチマークは次のようになります。
@Benchmark
public int intStreamRange() {
List<Integer> ret = IntStream.rangeClosed(begin, end).boxed().collect(Collectors.toList());
int total = 0;
for (int i : ret) {
total += i;
}
return total;
}
ここでは、非実体化ソリューションが依然として最速ですが、画像は大きく変化します。これが長さ=10です:
...そして長さ=10,000:
多くの要素にわたる長い反復は、物事を大幅に均等化しますが、日食とグアバは、10,000要素のテストでも2倍以上の速度を維持します。
したがって、本当に必要な場合はList<Integer>
、eclipseコレクションが最良の選択のように思われますが、もちろん、よりネイティブな方法でストリームを使用する場合(たとえば、.boxed()
プリミティブドメインを忘れて削減する場合)、これらすべてよりも速くなる可能性があります。バリアント。
1おそらく、エラー処理を除いて、たとえばend
<begin
の場合、またはサイズが実装またはJVMの制限を超えている場合(たとえば、。より大きい配列の場合)2^31-1
。