ある値からある値までの連続した値を持つList<Integer>
、あるいはInteger[]
またはを生成するための簡単で簡単な方法はありますか?int[]
start
end
つまり、次の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 個の要素のリストを作成するだけです。
- クラシック配列リスト: 私の質問で上記に示したコード (基本的には adarshr の回答と同じです)。
- eclipseコレクション: で与えられたコードドナルドの答え以下は Eclipse Collections 8.0 を使用した例です。
- グアバ範囲: で与えられたコードdavebの回答以下。技術的には、これは では
List<Integer>
なくを作成しますが、順番にContiguousSet<Integer>
実装されるため、私の目的にはほぼ適合します。Iterable<Integer>
- intストリーム範囲: で与えられたコードウラジミールの答え以下は、
IntStream.rangeClosed()
Java 8 で導入された - を使用しています。 - ストリーム反復: で与えられたコードカタリンの答え以下では、
IntStream
Java 8 で導入された機能も使用します。
以下は、サイズが 10 のリストを使用した上記のすべての結果 (キロ操作数/秒単位、数値が大きいほど良い) です。
...サイズが 10,000 のリストの場合も同様です。
最後のグラフは正しいです。EclipseとGuava以外のソリューションは、1ピクセルのバーも表示されないほど遅いです。高速なソリューションは10,000~20,000です。回他よりも速い。
もちろん、ここで起こっていることは、guava と eclipse のソリューションは実際には 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:
多くの要素に対する長い反復処理によって状況は大幅に改善されますが、Eclipse と Guava は 10,000 要素のテストでも 2 倍以上の速度を維持します。
だからもしあなたが本当にが必要な場合List<Integer>
は、Eclipse コレクションが最適な選択肢のようですが、もちろん、ストリームをよりネイティブな方法 (たとえば、.boxed()
プリミティブ ドメインを忘れて削減するなど) で使用すると、これらすべてのバリアントよりも高速になる可能性があります。
1end
おそらく、エラー処理 (たとえば、 <の場合begin
、またはサイズが実装または JVM の制限を超える場合 ( より大きい配列など))を除きます2^31-1
。
ベストアンサー1
Java 8 では非常にシンプルなので、別のメソッドも必要ありません。
List<Integer> range = IntStream.rangeClosed(start, end)
.boxed().collect(Collectors.toList());
Java 16 以降では次のようになります。
List<Integer> range = IntStream.rangeClosed(start, end)
.boxed().toList();