[英]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.