Daftar iterators menjamin pertama dan terutama bahwa Anda mendapatkan elemen daftar dalam urutan internal daftar (alias urutan penyisipan ). Lebih khusus itu dalam urutan Anda memasukkan elemen atau tentang bagaimana Anda memanipulasi daftar. Penyortiran dapat dilihat sebagai manipulasi struktur data, dan ada beberapa cara untuk menyortir daftar.
Saya akan memesan cara-cara dalam urutan kegunaan seperti yang saya pribadi melihatnya:
1. Pertimbangkan untuk menggunakan Set
atau Bag
koleksi sebagai gantinya
CATATAN: Saya menempatkan opsi ini di bagian atas karena ini adalah apa yang biasanya ingin Anda lakukan.
Kumpulan yang diurutkan secara otomatis mengurutkan koleksi pada saat penyisipan , yang berarti ia melakukan penyortiran saat Anda menambahkan elemen ke dalam koleksi. Ini juga berarti Anda tidak perlu mengurutkannya secara manual.
Selain itu, jika Anda yakin tidak perlu khawatir tentang (atau memiliki) elemen duplikat, Anda bisa menggunakannya TreeSet<T>
. Itu mengimplementasikan SortedSet
dan NavigableSet
antarmuka dan bekerja seperti yang mungkin Anda harapkan dari daftar:
TreeSet<String> set = new TreeSet<String>();
set.add("lol");
set.add("cat");
// automatically sorts natural order when adding
for (String s : set) {
System.out.println(s);
}
// Prints out "cat" and "lol"
Jika Anda tidak ingin pemesanan alami, Anda dapat menggunakan parameter konstruktor yang mengambil a Comparator<T>
.
Atau, Anda dapat menggunakan Multiset (juga dikenal sebagai Tas ) , yaitu Set
yang memungkinkan elemen duplikat, dan ada implementasi pihak ketiga. Terutama dari perpustakaan Jambu adaTreeMultiset
, yang bekerja sangat mirip TreeSet
.
2. Urutkan daftar Anda dengan Collections.sort()
Seperti disebutkan di atas, pengurutan List
s adalah manipulasi struktur data. Jadi untuk situasi di mana Anda membutuhkan "satu sumber kebenaran" yang akan diurutkan dalam berbagai cara, maka mengurutkannya secara manual adalah cara yang harus ditempuh.
Anda dapat mengurutkan daftar Anda dengan java.util.Collections.sort()
metode ini. Berikut ini contoh kode tentang caranya:
List<String> strings = new ArrayList<String>()
strings.add("lol");
strings.add("cat");
Collections.sort(strings);
for (String s : strings) {
System.out.println(s);
}
// Prints out "cat" and "lol"
Menggunakan pembanding
Salah satu manfaat yang jelas adalah bahwa Anda dapat menggunakan Comparator
dalam sort
metode. Java juga menyediakan beberapa implementasi untuk Comparator
seperti Collator
yang berguna untuk lokal string penyortiran sensitif. Ini salah satu contohnya:
Collator usCollator = Collator.getInstance(Locale.US);
usCollator.setStrength(Collator.PRIMARY); // ignores casing
Collections.sort(strings, usCollator);
Menyortir dalam lingkungan berbarengan
Namun perlu dicatat bahwa menggunakan sort
metode ini tidak ramah di lingkungan bersamaan, karena instance koleksi akan dimanipulasi, dan Anda sebaiknya mempertimbangkan untuk menggunakan koleksi yang tidak dapat diubah. Ini adalah sesuatu yang disediakan oleh Guava di Ordering
kelas dan merupakan one-liner sederhana:
List<string> sorted = Ordering.natural().sortedCopy(strings);
3. Bungkus daftar Anda dengan java.util.PriorityQueue
Meskipun tidak ada daftar yang diurutkan di Jawa, namun ada antrian yang diurutkan yang mungkin akan bekerja dengan baik untuk Anda. Itu java.util.PriorityQueue
kelasnya.
Nico Haase menautkan di komentar ke pertanyaan terkait yang juga menjawab ini.
Dalam koleksi yang diurutkan Anda kemungkinan besar tidak ingin memanipulasi struktur data internal yang mengapa PriorityQueue tidak mengimplementasikan antarmuka Daftar (karena itu akan memberi Anda akses langsung ke elemen-elemennya).
Peringatan pada PriorityQueue
iterator
The PriorityQueue
kelas alat yang Iterable<E>
dan Collection<E>
antarmuka sehingga dapat mengulangi seperti biasa. Namun, iterator tidak dijamin untuk mengembalikan elemen dalam urutan yang diurutkan. Alih-alih (seperti yang ditunjukkan Alderath dalam komentar), Anda harus poll()
mengantri sampai kosong.
Perhatikan bahwa Anda dapat mengonversi daftar ke antrian prioritas melalui konstruktor yang mengambil koleksi apa pun :
List<String> strings = new ArrayList<String>()
strings.add("lol");
strings.add("cat");
PriorityQueue<String> sortedStrings = new PriorityQueue(strings);
while(!sortedStrings.isEmpty()) {
System.out.println(sortedStrings.poll());
}
// Prints out "cat" and "lol"
4. Tulis SortedList
kelas Anda sendiri
CATATAN: Anda tidak harus melakukan ini.
Anda bisa menulis kelas Daftar Anda sendiri yang mengurutkan setiap kali Anda menambahkan elemen baru. Ini bisa menjadi perhitungan yang berat tergantung pada implementasi Anda dan tidak ada gunanya , kecuali jika Anda ingin melakukannya sebagai latihan, karena dua alasan utama:
- Itu melanggar kontrak yang
List<E>
dimiliki antarmuka karena add
metode harus memastikan bahwa elemen akan berada dalam indeks yang ditentukan pengguna.
- Mengapa menemukan kembali roda? Anda harus menggunakan TreeSet atau Multisets sebagai gantinya seperti yang ditunjukkan pada poin pertama di atas.
Namun, jika Anda ingin melakukannya sebagai latihan di sini adalah contoh kode untuk Anda mulai, menggunakan AbstractList
kelas abstrak:
public class SortedList<E> extends AbstractList<E> {
private ArrayList<E> internalList = new ArrayList<E>();
// Note that add(E e) in AbstractList is calling this one
@Override
public void add(int position, E e) {
internalList.add(e);
Collections.sort(internalList, null);
}
@Override
public E get(int i) {
return internalList.get(i);
}
@Override
public int size() {
return internalList.size();
}
}
Perhatikan bahwa jika Anda belum mengganti metode yang Anda butuhkan, maka implementasi default dari AbstractList
akan membuang UnsupportedOperationException
.