2015-03-02 45 views
0

我有一個數據類如下:JAVA:SomeStructure <E>使其按另一類型T排序?

class MyData { private UUID id; private String data1; private String data2} 

我它的實例存儲在一個地圖:

private Map<UUID, MyData> myData; 

正如我們所知道的,我可以通過UUID得到MyData的實例:

MyData instance = myData.get(UUID); 

但我也需要通過索引獲取MyData實例。更重要的是,索引按MyData.data1字段排序。所以我需要一個新的數據結構來存儲UUID根據索引順序,也許是這樣的:

private SomeStructure<UUID> myDataIndex; 

我想這是SomeStructure類。它應該有一個公開的方法,如:

public UUID getUuidByIndex(int index); 

而且,它應該通過MyData.data1字段排序UUID元素。

而且,每當我將物品放入private Map<UUID, MyData> myData時,物品的UUID也會添加到private SomeStructure<UUID> myDataIndex。我認爲這是性能方面的考慮,當我通過索引獲取元素時,不會生成ArrayList或其他東西。

對此SomeStructure有任何意見?我會更多地瞭解擴展或實現已知JAVA數據結構的方法。當然,完全定製的結構也受到高度讚賞。

爲了讓你完全明白我的問題,我想說明我的情況:

  1. 爲什麼我有地圖?我想通過UUID獲取數據。

  2. 爲什麼我要SomeStructure?我想通過索引來獲取數據。

爲了簡單起見:我想通過兩種不同的方式迭代我的數據。

非常感謝!

+0

我刪除了我的答案,但我仍然認爲答案可能是使用[如何對Java中的值排序Map ?](http:// stackoverflow。 COM /問題/ 109383 /如何到排序-A-映射鍵 - 值 - 上的值,在Java的)。 – 2015-03-02 13:13:12

回答

2

使用Sort a Map<Key, Value> by values (Java)中的技術之一生成排序映射,該映射根據您的值進行排序。

一旦你有這樣的地圖,你可以訪問使用其代碼爲指標的項目,如:

MyData item = new ArrayList<MyData>(myData.values()).get(index); 

你可以通過它的UUID與正常get(UUID)訪問。

+0

thx您的建議。但我不同意你的看法。根據JAVA文檔,TreeMap按KEY排序,甚至比較器與KEY有關但不是VALUE:這是它的構造函數:TreeMap(比較器比較器)。 – 2015-03-02 13:03:05

+0

MyData item = new ArrayList (myData.values())。get(index); < - 我認爲這種方法性能低下:每次我按索引得到一個元素,我應該新增一個ArrayList?不,我不這麼認爲。這就是爲什麼我有一個「私人SomeStructure myDataIndex;」。 – 2015-03-02 13:04:51

+0

@McArthorLee對不起,你對關鍵的排序是正確的。我現在要刪除這個。 – 2015-03-02 13:06:53

0

把你的元素在ArrayList<MyData>

ArrayList<MyData> dataAsList = new ArrayList<>(); 
dataAsList.addAll(myData.values()); 

Collections.sort(dataAsList, new Comparator() { 
    public int compare(MyData d1, MyData d2) { 
     return d1.data1.compareTo(d2.data2); 
}); 

// get the 3rd element 
MyData third = dataAsList.get(2); 

定製Comparator根據您的需要,例如,如果data1data2可以爲空,那麼一些空的檢查應予以補充。

+0

如果我想通過UUID獲取數據,該怎麼辦?我不想迭代整個ArrayList ......對不起,我編輯了我的帖子,試圖讓我的問題更清楚。 – 2015-03-02 13:13:39

+0

我不是故意替換你的地圖。保留它以供UUID訪問。您將不會有一個數據結構,即使使用SortedMap或SortedSet,也可以按索引進行關聯(鍵,值)**和**訪問。順便說一句,我明白你想通過_another_字段進行排序,而不是UUID(這是關鍵字)。這意味着你需要一個額外的結構來按照你想要的方式對元素進行排序。 – 2015-03-02 13:21:50

+0

感謝阿貝(法國?)。我明天會檢查你的方法。 – 2015-03-02 13:45:38

0

您指定兩個完全不同的要求(由UUID在排序列表中搜索和訪問由指數),所以你需要的是兩種不同的數據結構,即冗餘集合:

  1. 一個Map<UUID, MyData>做查找通過UUID
  2. 這是由data1

當然名稱排序List<MyData>,你可以 - 也應該 - 同時封裝後面的門面,通過控制訪問,以確保數據的完整性底層數據結構:

public class MyDataCollection { 
    private final Map<UUID, MyData> uuidToDataMap = new HashMap<>(); 
    private final List<MyData> sortedList = new ArrayList<>(); 

    /* read-only list */ 
    public List<MyData> getSortedList() { 
     return Collections.unmodifiableList(sortedList); 
    } 

    /* read-only map */ 
    public Map<UUID, MyData> getUuidToDataMap() { 
     return Collections.unmodifiableMap(uuidToDataMap); 
    } 

    public void add(MyData data) { 
     if (uuidToDataMap.contains(data.uuid)) { 
      // UUID already existing 
      // => throw exception, etc. 
     } 
     uuidToDataMap.put(data.uuid, data); 

     // insert into sorted list 
     // use binary search to find insertion point (see javadoc) 
     int index = Collections.binarySearch(sortedList, data); 
     if (index < 0) index = -index - 1; // insertion point 
     else index++; // insert after existing element 
     sortedList.add(index, data); 
    } 

    public boolean remove(MyData data) { 
     if (uuidToDataMap.remove(data.uuid) == data) { 
      sortedList.remove(data); 
      return true; 
     } 

     return false; 
    } 
} 

注:此代碼示例假定您的MyDataComparabledata1場。如果不是這種情況,則Comparator必須在Collections.binarySearch(...)中實施和使用。