いくつかのstart
値からend
値までの連続した値で、List<Integer>
、またはおそらくInteger[]
またはint[]
を生成するための短くて甘い方法はありますか?
つまり、より短いが、同等の何か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とサードパーティライブラリの両方を使用したいくつかの良い回答があったので、すべてのソリューションのパフォーマンスをテストすると思いました。
最初のテストは、次のメソッドを使用して、10個の要素のリスト[1..10]
の作成をテストするだけです。
List<Integer>
を作成するのではなく、ContiguousSet<Integer>
を作成しますが、Iterable<Integer>
を順番に実装するため、ほとんどの場合、目的に合わせて機能します。IntStream.rangeClosed()
を使用します。IntStream
機能も使用します8。サイズ10のリストを使用した上記のすべてについて、1秒あたりのキロオペレーション数の結果を示します(数値が大きいほど良い)。
...サイズ10,000のリストの場合:
最後のチャートは正しいです。EclipseとGuava以外のソリューションは遅すぎて、単一のピクセルバーを取得することさえできません。高速ソリューションは、10,000〜20,000times他よりも高速です。
もちろん、ここで起こっているのは、グアバと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;
}
ここでは、非実体化ソリューションが依然として最速ですが、写真は大きく変わります。 length = 10は次のとおりです。
...および長さ= 10,000:
多くの要素の長い反復により、状況は大幅に改善されますが、Eclipseとguavaは、10,000要素のテストでも2倍以上の速度を維持します。
したがって、本当にList<Integer>
が必要な場合、Eclipseコレクションが最良の選択のように見えますが、もちろん、よりネイティブな方法でストリームを使用する場合(たとえば、.boxed()
を忘れて、原始領域の縮小を行う)、おそらくこれらすべてのバリアントよりも高速になります。
1 おそらく、end
<begin
の場合、またはサイズが実装またはJVMの制限を超える場合(たとえば、2^31-1
より大きい配列の場合)のエラー処理を除きます。
Java 8を使用すると、非常に単純なので、別のメソッドも必要ありません。
List<Integer> range = IntStream.rangeClosed(start, end)
.boxed().collect(Collectors.toList());
まあ、この1つのライナーが資格を得る可能性があります(使用 グアバ範囲 )
ContiguousSet<Integer> integerList = ContiguousSet.create(Range.closedOpen(0, 10), DiscreteDomain.integers());
System.out.println(integerList);
これはList<Integer>
を作成しませんが、ContiguousSet
はほとんど同じ機能を提供し、特にInteger<Integer>
と同じ方法でforeach
実装を許可するList<Integer>
を実装します。
古いバージョン(Guava 14より前)では、これを使用できます。
ImmutableList<Integer> integerList = Ranges.closedOpen(0, 10).asSet(DiscreteDomains.integers()).asList();
System.out.println(integerList);
両方が生成します:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
次のワンライナーJava 8バージョンは[1、2、3、3 ... 10]を生成します。 iterate
の最初の引数はシーケンスの最初のnrであり、limit
の最初の引数は最後の数字です。
List<Integer> numbers = Stream.iterate(1, n -> n + 1)
.limit(10)
.collect(Collectors.toList());
これは、Core Javaを使用して得られる最短の時間です。
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;
}
Interval
クラスを Eclipse Collections から使用できます。
List<Integer> range = Interval.oneTo(10);
range.forEach(System.out::print); // prints 12345678910
Interval
クラスは遅延しているため、すべての値を格納するわけではありません。
LazyIterable<Integer> range = Interval.oneTo(10);
System.out.println(range.makeString(",")); // prints 1,2,3,4,5,6,7,8,9,10
メソッドは次のように実装できます。
public List<Integer> makeSequence(int begin, int end) {
return Interval.fromTo(begin, end);
}
Intを整数としてボックス化することを避けたいが、結果としてリスト構造が必要な場合は、Eclipse Collectionsの IntList
を IntInterval
とともに使用できます。
public IntList makeSequence(int begin, int end) {
return IntInterval.fromTo(begin, end);
}
IntList
には、インターフェイスで使用可能なメソッドsum()
、min()
、minIfEmpty()
、max()
、maxIfEmpty()
、average()
、およびmedian()
があります。
わかりやすくするために更新:2017/11/27
Interval
はList<Integer>
ですが、レイジーで不変です。特にコレクションを大量に処理する場合は、テストデータの生成に非常に役立ちます。必要に応じて、次のように間隔をList
、Set
、またはBag
に簡単にコピーできます。
Interval integers = Interval.oneTo(10);
Set<Integer> set = integers.toSet();
List<Integer> list = integers.toList();
Bag<Integer> bag = integers.toBag();
IntInterval
は、ImmutableIntList
を拡張するIntList
です。コンバーターメソッドもあります。
IntInterval ints = IntInterval.oneTo(10);
IntSet set = ints.toSet();
IntList list = ints.toList();
IntBag bag = ints.toBag();
Interval
とIntInterval
には、同じequals
コントラクトがありません。
プリミティブストリームからプリミティブコレクションを作成できるようになりました。好みに応じてwithAll
およびofAll
メソッドがあります。好奇心が強い人は、なぜ here の両方があるのかを説明する。これらのメソッドは、可変および不変のInt/Long/Doubleリスト、セット、バッグ、スタック用に存在します。
Assert.assertEquals(
IntInterval.oneTo(10),
IntLists.mutable.withAll(IntStream.rangeClosed(1, 10)));
Assert.assertEquals(
IntInterval.oneTo(10),
IntLists.immutable.withAll(IntStream.rangeClosed(1, 10)));
注:私はEclipseコレクションのコミッターです
Guava Ranges を使用できます
を使用してSortedSet
を取得できます
ImmutableSortedSet<Integer> set = Ranges.open(1, 5).asSet(DiscreteDomains.integers());
// set contains [2, 3, 4]
これは私が見つけることができる最短です。
リストバージョン
public List<Integer> makeSequence(int begin, int end)
{
List<Integer> ret = new ArrayList<Integer>(++end - begin);
for (; begin < end; )
ret.add(begin++);
return ret;
}
配列バージョン
public int[] makeSequence(int begin, int end)
{
if(end < begin)
return null;
int[] ret = new int[++end - begin];
for (int i=0; begin < end; )
ret[i++] = begin++;
return ret;
}