繁体   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