Đây là việc thực hiện các phương pháp toSet()
lớp của java.util.stream.Collectors
:Sử dụng API Java 8 luồng, có thể sắp xếp() được dựa vào khi gọi Collectors.toSet()?
public static <T>
Collector<T, ?, Set<T>> toSet() {
return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
(left, right) -> { left.addAll(right); return left; },
CH_UNORDERED_ID);
}
Như chúng ta có thể thấy, nó sử dụng một HashSet
và gọi add
. Từ HashSet
documentation, "Nó không đảm bảo về thứ tự lặp của tập hợp; đặc biệt, nó không đảm bảo rằng thứ tự sẽ không thay đổi theo thời gian".
Trong đoạn mã sau, một List
của String
được xem trực tiếp, sắp xếp và tổng hợp theo một Set
:
public static void main(String[] args) {
Set<String> strings = Arrays.asList("c", "a", "b")
.stream()
.sorted()
.collect(Collectors.toSet());
System.out.println(strings.getClass());
System.out.println(strings);
}
này cung cấp kết quả:
class java.util.HashSet
[a, b, c]
Các đầu ra được sắp xếp. Điều tôi nghĩ đang xảy ra ở đây là mặc dù hợp đồng được cung cấp bởi tài liệu HashSet
chỉ định rằng thứ tự không phải là thứ mà nó cung cấp, việc triển khai sẽ xảy ra để thêm vào thứ tự. Tôi cho rằng điều này có thể thay đổi trong các phiên bản tương lai/khác nhau giữa các JVM và cách tiếp cận khôn ngoan hơn là làm một cái gì đó như Collectors.toCollection(TreeSet::new)
.
Có thể sorted()
được dựa vào khi gọi Collectors.toSet()
không?
Ngoài ra, chính xác những gì "nó không đảm bảo rằng thứ tự sẽ không đổi theo thời gian" nghĩa là gì? (Tôi giả sử add
, remove
, việc thay đổi kích thước của mảng cơ bản?)
"Có thể sắp xếp() được dựa vào khi gọi Collectors.toSet()?" Không. [Ví dụ] (https://ideone.com/NPVQT8). –
Nếu duy trì bất kỳ thứ tự nào trong các trường hợp JVM khác nhau (và/hoặc các chu kỳ phát hành JVM khác nhau) là cần thiết, người ta phải sử dụng 'LinkedHashSet' hoặc các lớp tương tự đảm bảo thứ tự ** xác định **. Lý do được đưa ra trong các câu trả lời đã có. – Zabuza