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