2010-06-14 23 views
5

Tôi cần một tập hợp các đối tượng được sắp xếp và hiện đang sử dụng TreeSet. Vấn đề của tôi là compareTo của các đối tượng sẽ thường trả về 0, có nghĩa là thứ tự của hai đối tượng đó không bị thay đổi. TreeMap (được sử dụng bởi TreeSet theo mặc định) sau đó sẽ coi chúng là cùng một đối tượng, điều này không đúng.CompareTo có thể trả về 0, thay thế cho TreeSet/TreeMap

Tôi có thể sử dụng phương án thay thế nào cho TreeMap?


Trường hợp sử dụng: Tôi có một bộ đối tượng có thể hiển thị. Tôi muốn sắp xếp chúng theo Y phối hợp, để chúng được kết xuất theo đúng thứ tự. Tất nhiên, hai đối tượng có thể có cùng tọa độ Y.

+0

Nếu hai yếu tố có cùng Y phối hợp, những gì bạn ** bạn ** đặt Đầu tiên? Có tiêu chí nào khác không? – OscarRyz

Trả lời

9

Bạn đang xác định một tiêu chí để so sánh, nhưng bạn cần thêm tiêu chí bổ sung.

Bạn nói:

Tôi có một tập các đối tượng thể hiển thị. Tôi muốn sắp xếp chúng theo Y phối hợp, để chúng được kết xuất theo đúng thứ tự. Tất nhiên, hai đối tượng có thể có cùng tọa độ Y.

Vì vậy, nếu hai yếu tố có cùng toạ độ Y, bạn đặt gì trước? Tiêu chuẩn khác là gì?

Nó có thể là thời gian sáng tạo, nó có thể là tọa độ x, bạn chỉ cần phải xác định nó:

Map<String,Thing> map = new TreeMap<String,Thing>(new Comparator<Thing>(){ 
    public int compare(Thing one, Thing two) { 
     int result = one.y - two.y; 
     if(result == 0) { // same y coordinate use another criteria 
      result = one.x - two.x; 
      if(result == 0) { //still the same? Try another criteria (maybe creation time 
       return one.creationTime - two.creationTime 
      } 
      } 
      return result; 
    } 
}); 

Bạn phải xác định khi một Thing cao/thấp/bằng/hơn Thing khác. Nếu một trong các thuộc tính giống với các thuộc tính khác, có thể bạn không nên di chuyển chúng. Nếu có thuộc tính khác để so sánh việc sử dụng nó.

+0

Một câu lệnh if! Tại sao tôi không nghĩ về điều đó và thay vào đó đã viết một chút xấu xí chuyển hack: p –

+0

lol ... đôi khi tâm trí của chúng tôi lặp đi lặp lại quá xa, và chúng tôi chỉ cần một ai đó từ bên ngoài để làm cho chúng ta nhìn theo hướng * rõ ràng *. * Glasse của tôi đâu rồi? - ehrm ... Bạn đang mặc chúng * loại :) – OscarRyz

0

Tôi có một ý tưởng của riêng tôi, nhưng đó là nhiều hơn một workaround

int compare(Object a, Object b) { 
    an = a.seq + (a.sortkey << 16); // allowing for 65k items in the set 
    bn = b.seq + (a.sortKey << 16); 
    return an - bn; // can never remember whether it's supposed to be this or b - a. 
} 
  • sortKey = những gì thực sự quan trọng cho việc phân loại, ví dụ một Y phối hợp
  • seq = a số thứ tự gán đối tượng khi được thêm vào tập hợp
0

Có 2 điều quan trọng cần nhớ khi sử dụng các bộ được sắp xếp (ví dụ: TreeSet):

1) Chúng được đặt; hai yếu tố bình đẳng không được phép trong bộ sưu tập cùng

2) Bình đẳng phải phù hợp với cơ chế so sánh (hoặc so sánh hoặc tương đương)

Vì vậy, trong trường hợp của bạn, bạn nên "phá vỡ mối quan hệ" bằng cách thêm một số đặt hàng thứ cấp tiêu chí. Ví dụ: đầu tiên sử dụng trục Y, sau đó X, và sau đó một số định danh đối tượng duy nhất.

Xem thêm http://eyalsch.wordpress.com/2009/11/23/comparators/

2

Vấn đề bạn đang chạy vào đó là compareTo trở 0 có nghĩa là các đối tượng đều bình đẳng.Đồng thời, bạn đặt chúng vào một tập hợp, không cho phép nhiều bản sao của các phần tử bằng nhau.

Hoặc viết lại compareTo để các phần tử không bằng nhau trả lại các giá trị khác nhau hoặc sử dụng một cái gì đó như java.util.PriorityQueue cho phép nhiều bản sao của các phần tử bằng nhau.

1

Tôi đã thực hiện việc này trước đây. Đó là một bản đồ đa lệnh được đặt hàng và nó chỉ là một TreeMap của các đối tượng List. Như thế này ..

Map<KeyType, List<ValueType>> mmap = new TreeMap<KeyType, List<ValueType>>(); 

Bạn cần tạo một LinkedList mới mỗi khi một khóa mới được giới thiệu, vì vậy có thể hữu ích khi quấn nó trong một lớp chứa tùy chỉnh. Tôi sẽ cố tìm thứ gì đó.


Vì vậy, tôi đã ném thùng chứa tùy chỉnh này lại với nhau một cách nhanh chóng (hoàn toàn chưa được kiểm tra), nhưng đó có thể là những gì bạn đang tìm kiếm. Hãy nhớ rằng bạn chỉ nên sử dụng loại vùng chứa này nếu bạn thực sự đang tìm kiếm bản đồ danh sách giá trị được sắp xếp. Nếu có một số thứ tự tự nhiên cho giá trị của bạn, bạn nên sử dụng TreeSet như những người khác đã đề xuất.

import java.util.LinkedList; 
import java.util.List; 
import java.util.Map; 
import java.util.Set; 
import java.util.TreeMap; 

public class MTreeMap<K, V> { 

    private final Map<K, List<V>> mmap = new TreeMap<K, List<V>>(); 
    private int size = 0; 

    public MTreeMap() { 
    } 

    public void clear() { 
     mmap.clear(); 
     size=0; 
    } 

    public boolean containsKey(K key) { 
     return mmap.containsKey(key); 
    } 

    public List<V> get(K key) { 
     return mmap.get(key); 
    } 

    public boolean isEmpty() { 
     return mmap.isEmpty(); 
    } 

    public Set<K> keySet() { 
     return mmap.keySet(); 
    } 

    public Collection<List<V>> valueLists() { 
     return mmap.values(); 
    } 

    public void put(K key, V value) { 

     List<V> vlist = mmap.get(key); 
     if (null==vlist) { 
     vlist = new LinkedList<V>(); 
     mmap.put(key, vlist); 
     } 
     vlist.add(value); 
     ++size; 
    } 

    public List<V> remove(Object key) { 
     List<V> vlist = mmap.remove(key); 

     if (null!=vlist) { 
     size = size - vlist.size() ; 
     } 
     return vlist; 
    } 

    public int size() { 
     return size; 
    } 

    public String toString() { 
     return mmap.toString(); 
    } 

} 

Dưới đây là một thử nghiệm thô sơ:

public class TestAnything { 

    public static void main(String[] args) { 

     MTreeMap<Integer, String> mmap = new MTreeMap<Integer, String>(); 

     mmap.put(1, "Value1"); 
     mmap.put(2, "Value2"); 
     mmap.put(3, "Value3"); 
     mmap.put(1, "Value4"); 
     mmap.put(3, "Value5"); 
     mmap.put(2, "Value6"); 
     mmap.put(2, "Value7"); 

     System.out.println("size (1) = " + mmap.get(1).size()); 
     System.out.println("size (2) = " + mmap.get(2).size()); 
     System.out.println("size (3) = " + mmap.get(3).size()); 
     System.out.println("Total size = " + mmap.size()); 

     System.out.println(mmap); 
    } 

} 

Kết quả là thế này:

size (1) = 2 
size (2) = 3 
size (3) = 2 
Total size = 7 
{1=[Value1, Value4], 2=[Value2, Value6, Value7], 3=[Value3, Value5]}