2011-11-18 26 views
77

我試圖在Java中同時找到java.util.Listjava.util.Set的實現。我想讓這個類僅允許唯一的元素(如Set)並保留它們的順序(如List)。它存在於JDK 6中嗎?是否還有一個保存的插入順序Set也實現List?

重要的是要有List<T>#add(int, T),這樣我才能插入到特定位置。

+0

你的意思是保留它們的**插入**順序或由一個「比較器」定義的順序?你也想要'List'接口的語義嗎? –

回答

183

TreeSet按元素順序排列; LinkedHashSet保留廣告訂單。希望這些之一是你以後的。

你指定你希望能夠在任意位置插入,我懷疑你必須寫自己 - 只是創建一個包含HashSet<T>ArrayList<T>一類;添加項目時,請在將其添加到列表之前檢查它是否在設置中。

+0

那麼,問題是,它沒有'List#add(int,T)'方法.. – yegor256

+9

@ yegor256:如果你事先說過...編輯它會很有用。 –

10

你是說像LinkedHashSet?這保留了輸入的順序,但不允許重複。

恕我直言,它的一個不尋常的要求,但你可以寫一個列表沒有重複。

class SetList<T> extends ArrayList<T> { 
    @Override 
    public boolean add(T t) { 
     return !super.contains(t) && super.add(t); 
    } 

    @Override 
    public void add(int index, T element) { 
     if (!super.contains(element)) super.add(index, element); 
    } 

    @Override 
    public boolean addAll(Collection<? extends T> c) { 
     boolean added = false; 
     for (T t : c) 
      added |= add(t); 
     return added; 
    } 

    @Override 
    public boolean addAll(int index, Collection<? extends T> c) { 
     boolean added = false; 
     for (T t : c) 
      if (!super.contains(t)) { 
       super.add(index++, t); 
       added = true; 
      } 
     return added; 
    } 
} 
+0

它沒有實現'List'接口,請參閱我對 – yegor256

+1

http://stackoverflow.com/a/8185105/253468問題所做的更改,因爲它沒有'O(n)'插入複雜性,所以存在一個折衷我們必須考慮雙存儲和'O(log(n))'插入操作。 – TWiStErRob

5

您不能立即實施ListSet沒有違反合同。參見,例如,Set.hashCode合同:

一組的哈希碼被定義爲在所述一組,其中一空元素的哈希碼被定義爲元素的哈希碼的總和零。

在這裏另一方面是的List.hashCode合同:

列表的哈希碼定義爲以下計算的結果:

int hashCode = 1; 
for (E e : list) 
    hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); 

所以這不可能實施保證雙方合同履行的單一類別。 equals執行的同樣的問題。

0

我有類似的問題,所以我寫了我自己的。請參閱hereIndexedArraySet延伸ArrayList並實現Set,所以它應該支持所有你需要的操作。請注意,將元素插入ArrayList中間的位置對於大型列表可能會很慢,因爲以下所有元素都需要移動。我的IndexedArraySet不會改變這一點。

0

另一種選擇(減去List接口要求)是Guava的ImmutableSet,它保留了插入順序。來自their wiki page

除排序集合外,訂單從施工時間保留。例如,

ImmutableSet.of("a", "b", "c", "a", "d", "b") 

將遍歷其在順序 「一」 的元素, 「B」, 「C」, 「d」。

相關問題