2012-10-06 33 views
8

Tôi đã đăng một số mã here đã giải quyết chính xác vấn đề mà người đăng tải đã gặp phải. OP muốn xóa các bản sao và mang một số mặt hàng đặc biệt vào đầu danh sách. Tôi đã sử dụng một số TreeSet với lớp đặc biệt Comparable bọc Locale mà họ đang làm việc để đạt được những gì họ muốn.Bằng và so sánh với Bộ

sau đó tôi đã suy nghĩ ... khi bạn làm ... rằng tôi đã loại bỏ bản sao bằng cách quay 0 từ phương pháp compareTo, không bằng cách quay true từ một thực hiện equals như người ta sẽ cần phải làm gì để chỉ ra một cách chính xác là một bản sao trong một số Set (từ số definition của số Set).

Tôi không phản đối việc sử dụng kỹ thuật này nhưng tôi có đang sử dụng những gì có thể được coi là một tính năng không có giấy tờ không có giấy tờ không? Tôi có an toàn khi cho rằng việc thực hiện điều này sẽ tiếp tục hoạt động không?

+0

Như ông Nurkiewicz chỉ ra, điều này được quy định hành vi, vì vậy nó an toàn. Tôi đồng ý rằng điều đó thật đáng ngạc nhiên! –

Trả lời

17

Nó có vẻ như điều này được khá tốt tài liệu trong JavaDoc of TreeSet (mỏ đậm):

Lưu ý rằng thứ tự được duy trì bởi một bộ (đã hoặc chưa một so sánh rõ ràng được cung cấp) phải phù hợp với bằng nếu nó thực hiện đúng giao diện Set. (Xem Comparable hoặc Comparator cho một định nghĩa chính xác của phù hợp với chiều sâu.) Đây là như vậy bởi vì giao diện Set được định nghĩa về hoạt động equals, nhưng một trường hợp TreeSet thực hiện mọi sự so sánh yếu tố sử dụng phương phápcompareTo (hoặc so sánh) của nó, do đó, hai yếu tố được coi là bằng nhau theo phương pháp này, từ quan điểm của tập hợp, bằng nhau. Hành vi của tập hợp được xác định rõ ngay cả khi thứ tự của nó không nhất quán với bằng; nó không tuân theo hợp đồng chung của giao diện Set.

Dưới đây là một ví dụ về only (?) JDK class mà thực hiện Comparable nhưng không phù hợp với equals():

Set<BigDecimal> decimals = new HashSet<BigDecimal>(); 
decimals.add(new BigDecimal("42")); 
decimals.add(new BigDecimal("42.0")); 
decimals.add(new BigDecimal("42.00")); 
System.out.println(decimals); 

decimals ở cuối có ba giá trị vì 42, 42.042.00 không bằng nhau như xa như equals() là có liên quan. Nhưng nếu bạn thay thế HashSet bằng TreeSet, tập hợp kết quả chỉ chứa 1 mục (42 - điều đó xảy ra là mục đầu tiên được thêm) vì tất cả chúng được coi là bằng nhau khi so sánh bằng cách sử dụng BigDecimal.compareTo().

Điều này cho thấy TreeSet là một cách "chia" khi sử dụng các loại không phù hợp với equals(). Nó vẫn hoạt động đúng và tất cả các hoạt động được xác định rõ ràng - nó chỉ không tuân theo hợp đồng của lớp Set - nếu hai lớp không phải là equal(), chúng không được coi là trùng lặp.

Xem thêm

+0

Điều thú vị là không có nhận xét như vậy trong tài liệu 'ConcurrentSkipListSet'. – OldCurmudgeon

+1

@OldCurmudgeon Nó cũng được xác định trong [javadoc of SortedSet] (http://docs.oracle.com/javase/7/docs/api/java/util/SortedSet.html) (và cả TreeSet lẫn ConcurrentSkipListSet thực hiện điều đó giao diện). – assylias

+0

Vì vậy, nó !! Nắm bắt tốt. – OldCurmudgeon