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
.
sumber
Jawaban:
Dengan Java 8 itu sangat sederhana sehingga tidak memerlukan metode terpisah lagi:
sumber
Nah, liner yang satu ini mungkin memenuhi syarat (menggunakan Guava Ranges )
Ini tidak membuat
List<Integer>
, tetapiContiguousSet
menawarkan banyak fungsionalitas yang sama, khususnya penerapanIterable<Integer>
yang memungkinkanforeach
implementasi dengan cara yang sama sepertiList<Integer>
.Di versi lama (sebelum Guava 14) Anda bisa menggunakan ini:
Keduanya menghasilkan:
sumber
asList()
sana kecuali Anda benar-benar membutuhkanList
... yangContiguousSet
diproduksi olehasSet
ringan (hanya memerlukan jangkauan dan domain), tetapiasList()
akan membuat daftar yang benar-benar menyimpan semua elemen dalam memori (saat ini).Range
ada tetapi tidakRanges
dan mereka telah menghapusasSet
metode tersebut. Di versi lama saya,asSet
sudah usang dan tampaknya mereka telah menghapusnya. Rentang tampaknya hanya untuk digunakan untuk koleksi yang berdekatan dan mereka telah memberlakukannya meskipun saya sangat menyukai solusi ini.Versi Java 8 satu baris berikut akan menghasilkan [1, 2, 3 ... 10]. Argumen pertama
iterate
adalah nr pertama dalam barisan, dan argumen pertamalimit
adalah bilangan terakhir.sumber
Anda dapat menggunakan
Interval
kelas dari Koleksi Eclipse .The
Interval
kelas malas, sehingga tidak menyimpan semua nilai-nilai.Metode Anda akan dapat diterapkan sebagai berikut:
Jika Anda ingin menghindari tinju int sebagai Integer, tetapi tetap menginginkan struktur daftar sebagai hasilnya, Anda dapat menggunakan
IntList
withIntInterval
from Eclipse Collections.IntList
memiliki metodesum()
,min()
,minIfEmpty()
,max()
,maxIfEmpty()
,average()
danmedian()
tersedia pada antarmuka.Pembaruan untuk kejelasan: 11/27/2017
An
Interval
adalah aList<Integer>
, tetapi malas dan tidak dapat diubah. Ini sangat berguna untuk menghasilkan data pengujian, terutama jika Anda berurusan dengan banyak koleksi. Jika mau, Anda dapat dengan mudah menyalin interval keList
,Set
atauBag
sebagai berikut:An
IntInterval
adalahImmutableIntList
yang meluasIntList
. Ini juga memiliki metode konverter.An
Interval
dan anIntInterval
tidak memilikiequals
kontrak yang sama .Pembaruan untuk Koleksi Eclipse 9.0
Sekarang Anda dapat membuat koleksi primitif dari aliran primitif. Ada
withAll
danofAll
metode tergantung pada preferensi Anda. Jika Anda penasaran, saya jelaskan mengapa kita memiliki keduanya di sini . Metode ini ada untuk Int / Long / Double List, Sets, Bags dan Stacks yang dapat berubah dan tidak berubah.Catatan: Saya seorang pelaku untuk Koleksi Eclipse
sumber
Ini adalah waktu terpendek yang saya dapat menggunakan Core Java.
sumber
for(int i = begin; i <= end; ret.add(i++));
:)ret.add(i)
bagian ke penambahan loop for membuat ini "lebih pendek". Saya kira dengan logika itu jika saya menulis semuanya dalam satu baris, itu akan menjadi lebih pendek :)Anda bisa menggunakan Guava Ranges
Anda bisa mendapatkan
SortedSet
dengan menggunakansumber
Ini adalah waktu terpendek yang bisa saya temukan.
Versi daftar
Versi Array
sumber
Yang ini mungkin berhasil untuk Anda ....
sumber