Apakah ada cara yang singkat dan menarik untuk menghasilkan a List<Integer>
, atau mungkin an Integer[]
atau int[]
, dengan nilai berurutan dari beberapa start
nilai ke end
nilai?
Artinya, sesuatu yang lebih pendek dari, tetapi setara dengan 1 berikut ini:
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;
}
Penggunaan jambu biji boleh saja.
Memperbarui:
Analisis Kinerja
Karena pertanyaan ini telah menerima beberapa jawaban bagus, baik menggunakan Java 8 asli dan pustaka pihak ketiga, saya pikir saya akan menguji kinerja semua solusi.
Tes pertama hanya menguji pembuatan daftar 10 elemen [1..10]
menggunakan metode berikut:
- classicArrayList : kode yang diberikan di atas dalam pertanyaan saya (dan pada dasarnya sama dengan jawaban adarshr).
- eclipseCollections : kode yang diberikan dalam jawaban Donald di bawah ini menggunakan Eclipse Collections 8.0.
- guavaRange : kode yang diberikan dalam jawaban daveb di bawah ini. Secara teknis, ini tidak membuat
List<Integer>
melainkan aContiguousSet<Integer>
- tetapi karena diterapkanIterable<Integer>
secara berurutan, sebagian besar berfungsi untuk tujuan saya. - intStreamRange : kode yang diberikan dalam jawaban Vladimir di bawah ini, yang menggunakan
IntStream.rangeClosed()
- yang diperkenalkan di Java 8. - streamIterate : kode yang diberikan dalam jawaban Catalin di bawah ini yang juga menggunakan
IntStream
fungsionalitas yang diperkenalkan di Java 8.
Berikut adalah hasil dalam kilo-operasi per detik (angka yang lebih tinggi lebih baik), untuk semua di atas dengan daftar ukuran 10:
... dan sekali lagi untuk daftar ukuran 10.000:
Bagan terakhir itu benar - solusi selain Eclipse dan Guava terlalu lambat bahkan untuk mendapatkan satu batang piksel! Solusi cepatnya 10.000 hingga 20.000 kali lebih cepat daripada yang lain.
Apa yang terjadi di sini, tentu saja, adalah bahwa solusi jambu biji dan gerhana tidak benar-benar mewujudkan daftar 10.000 elemen apa pun - mereka hanya pembungkus berukuran tetap di sekitar titik awal dan akhir. Setiap elemen dibuat sesuai kebutuhan selama iterasi. Karena kami tidak benar-benar mengulang dalam pengujian ini, biayanya ditangguhkan. Semua solusi lain benar-benar mewujudkan daftar lengkap dalam memori dan membayar mahal dalam tolok ukur khusus kreasi.
Mari kita lakukan sesuatu yang sedikit lebih realistis dan juga mengulangi semua bilangan bulat, menjumlahkannya. Jadi dalam kasus IntStream.rangeClosed
varian, tolok ukurnya terlihat seperti:
@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;
}
Di sini, gambar banyak berubah, meskipun solusi yang tidak terwujud masih yang tercepat. Berikut panjangnya = 10:
... dan panjang = 10.000:
Iterasi panjang pada banyak elemen meratakan banyak hal, tetapi gerhana dan jambu biji tetap lebih dari dua kali lebih cepat bahkan pada uji 10.000 elemen.
Jadi jika Anda benar - benar menginginkan List<Integer>
, koleksi gerhana tampaknya pilihan terbaik - tetapi tentu saja jika Anda menggunakan aliran dengan cara yang lebih asli (misalnya, melupakan .boxed()
dan melakukan pengurangan dalam domain primitif) Anda mungkin akan berakhir lebih cepat daripada semua ini. varian.
1 Mungkin dengan pengecualian penanganan kesalahan, misalnya jika end
< begin
, atau jika ukurannya melebihi beberapa implementasi atau batas JVM (misalnya, array lebih besar dari 2^31-1
.