簡體   English   中英

使用自定義比較器時最好使用TreeSet或ArrayList

[英]Is it better to use a TreeSet or ArrayList when using a custom comparator

我已經實現了一個圖形。 我想針對其度對給定的頂點子集進行排序。 因此,我編寫了一個自定義比較器,命名為DegreeComparator

private class DegreeComparator implements Comparator<Integer>
{
    @Override
    public int compare(Integer arg0, Integer arg1) 
    {
        if(adj[arg1].size() == adj[arg0].size()) return arg1 - arg0;
        else return adj[arg1].size() - adj[arg0].size());
    }

}

那么,以下哪一項更有效?

使用TreeSet

public Collection<Integer> sort(Collection<Integer> unsorted)
{
    Set<Integer> sorted = new TreeSet<Integer>(new DegreeComparator());
    sorted.addAll(unsorted);
    return sorted;
}

使用ArrayList

Collections.sort(unsorted, new DegreeComparator());

注意,第二種方法不是函數,而是單行代碼。

憑直覺,我寧願選擇第二個。 但是我不確定它是否更有效。

在此處輸入圖片說明 Java API包含許多Collection和Map實現,因此弄清楚要使用哪個實現可能會造成混淆。 這是一個快速流程圖,可能有助於從最常見的實現中進行選擇

TreeSet是一個Set。 它將刪除重復項(具有相同程度的元素)。 因此,兩者並不等同。

無論如何,如果您自然需要排序列表,則對列表進行排序。 無論集合是否重復,這都將起作用,即使它的復雜度(O(n * log(n))與填充TreeSet相同),也可能更快(因為它只需要移動數組中的元素,而不需要創建很多樹節點)。

如果僅排序一次,則ArrayList無疑是贏家。 如果您經常添加或刪除項目,則TreeSet會更好,因為一次又一次地對列表進行排序會很慢。

還要注意,所有樹結構都需要更多的內存和間接訪問內存的方法,這會使它們變慢。


如果中型列表的情況經常由單個元素更改,則最快的解決方案可能是使用ArrayList並將其插入適當的位置(顯然是假設數組最初已排序)。

您需要通過Arrays.binarySearch確定插入位置,然后插入或移除。 實際上,除非性能非常關鍵,並且基准測試表明它會有所幫助,否則我不會這樣做。 當列表很大時,它會變慢,並且增益受到限制,因為Java使用了針對這種情況進行了優化的TimSort


正如評論中指出的那樣,確保Comparator返回不同的值有時並非易事。 幸運的是,有番石榴的Ordering#arbitrary ,如果您不需要與equals兼容,它可以解決此問題。 如果您這樣做,可以編寫類似的方法(如果需要,我敢肯定我可以在某個地方找到它)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM