Trình lặp danh sách đảm bảo đầu tiên và trước hết là bạn có được các phần tử của danh sách theo thứ tự nội bộ của danh sách (hay còn gọi là thứ tự chèn ). Cụ thể hơn, đó là theo thứ tự bạn đã chèn các yếu tố hoặc về cách bạn thao tác danh sách. Sắp xếp có thể được xem như là một thao tác của cấu trúc dữ liệu và có một số cách để sắp xếp danh sách.
Tôi sẽ sắp xếp các cách theo thứ tự hữu ích như cá nhân tôi thấy:
1. Xem xét sử dụng Set
hoặc Bag
bộ sưu tập thay thế
LƯU Ý: Tôi đặt tùy chọn này lên hàng đầu vì đây là điều bạn thường muốn làm.
Một tập hợp được sắp xếp tự động sắp xếp bộ sưu tập khi chèn , nghĩa là nó sắp xếp trong khi bạn thêm các phần tử vào bộ sưu tập. Điều đó cũng có nghĩa là bạn không cần phải tự sắp xếp nó.
Hơn nữa, nếu bạn chắc chắn rằng bạn không cần phải lo lắng về (hoặc có) các yếu tố trùng lặp thì bạn có thể sử dụng TreeSet<T>
thay thế. Nó thực hiện SortedSet
và NavigableSet
giao diện và hoạt động như bạn có thể mong đợi từ một danh sách:
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"
Nếu bạn không muốn thứ tự tự nhiên, bạn có thể sử dụng tham số hàm tạo có một Comparator<T>
.
Ngoài ra, bạn có thể sử dụng Multisets (còn được gọi là Túi ) , nghĩa là Set
cho phép các yếu tố trùng lặp, thay vào đó và có các triển khai của bên thứ ba. Đáng chú ý nhất là từ các thư viện Guava có một TreeMultiset
, hoạt động rất giống như TreeSet
.
2. Sắp xếp danh sách của bạn với Collections.sort()
Như đã đề cập ở trên, sắp xếp List
s là một thao tác của cấu trúc dữ liệu. Vì vậy, đối với các tình huống mà bạn cần "một nguồn sự thật" sẽ được sắp xếp theo nhiều cách khác nhau thì sắp xếp nó theo cách thủ công là cách tốt nhất.
Bạn có thể sắp xếp danh sách của bạn với java.util.Collections.sort()
phương pháp. Đây là một mẫu mã về cách:
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"
Sử dụng bộ so sánh
Một lợi ích rõ ràng là bạn có thể sử dụng Comparator
trong sort
phương pháp. Java cũng cung cấp một số triển khai cho Comparator
ví dụ như Collator
hữu ích cho các chuỗi sắp xếp nhạy cảm cục bộ . Đây là một ví dụ:
Collator usCollator = Collator.getInstance(Locale.US);
usCollator.setStrength(Collator.PRIMARY); // ignores casing
Collections.sort(strings, usCollator);
Sắp xếp trong môi trường đồng thời
Tuy nhiên, xin lưu ý rằng việc sử dụng sort
phương thức này không thân thiện trong các môi trường đồng thời, vì thể hiện của bộ sưu tập sẽ bị thao túng và thay vào đó bạn nên xem xét sử dụng các bộ sưu tập bất biến. Đây là thứ mà Guava cung cấp trong Ordering
lớp và là một lớp lót đơn giản:
List<string> sorted = Ordering.natural().sortedCopy(strings);
3. Gói danh sách của bạn với java.util.PriorityQueue
Mặc dù không có danh sách được sắp xếp trong Java, tuy nhiên có một hàng đợi được sắp xếp có thể sẽ hoạt động tốt cho bạn. Đó là java.util.PriorityQueue
lớp học.
Nico Haase liên kết trong các ý kiến với một câu hỏi liên quan cũng trả lời điều này.
Trong bộ sưu tập được sắp xếp, rất có thể bạn không muốn thao túng cấu trúc dữ liệu nội bộ, đó là lý do PriorityQueue không triển khai giao diện Danh sách (vì điều đó sẽ cho phép bạn truy cập trực tiếp vào các phần tử của nó).
Hãy cẩn thận trên PriorityQueue
iterator
Các PriorityQueue
dụng cụ lớp Iterable<E>
và Collection<E>
giao diện để nó có thể được lặp như bình thường. Tuy nhiên, iterator không được đảm bảo trả về các phần tử theo thứ tự được sắp xếp. Thay vào đó (như Alderath chỉ ra trong các bình luận) bạn cần poll()
xếp hàng cho đến khi trống.
Lưu ý rằng bạn có thể chuyển đổi danh sách thành hàng đợi ưu tiên thông qua hàm tạo có bất kỳ bộ sưu tập nào :
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. Viết SortedList
lớp của riêng bạn
LƯU Ý: Bạn không cần phải làm điều này.
Bạn có thể viết lớp Danh sách của riêng bạn sắp xếp mỗi khi bạn thêm một phần tử mới. Điều này có thể trở nên khá nặng nề tính toán tùy thuộc vào việc thực hiện của bạn và là vô nghĩa , trừ khi bạn muốn thực hiện nó như một bài tập, vì hai lý do chính:
- Nó phá vỡ hợp đồng mà
List<E>
giao diện có vì các add
phương thức sẽ đảm bảo rằng phần tử sẽ nằm trong chỉ mục mà người dùng chỉ định.
- Tại sao phải phát minh lại bánh xe? Thay vào đó, bạn nên sử dụng TreeSet hoặc Multisets như được chỉ ra ở điểm đầu tiên ở trên.
Tuy nhiên, nếu bạn muốn thực hiện nó như một bài tập ở đây là một mẫu mã để bạn bắt đầu, nó sử dụng AbstractList
lớp trừu tượng:
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();
}
}
Lưu ý rằng nếu bạn chưa ghi đè các phương thức bạn cần, thì các cài đặt mặc định từ đó AbstractList
sẽ ném UnsupportedOperationException
s.