用Java中的几个比较器对列表进行排序的有效方法

时间:2014-01-23 20:56:04

标签: java sorting optimization performance

抱歉我的英文。

我有这样的事情:

class SomeClass<T> {
    private List<T> elements;
    private List<Comparator<T>> comparators;

    public SomeClass(List<T> elements) {
        this.elements = elements;
        this.comparators = new ArrayList<Comparator<T>>();
    }

    public void addComparator(Comparator<T> comparator) {
        comparators.add(comparator);
    }

    public List<T> getSortedElements() {
        return sorted(new ArrayList<T>(elements));
    }

    // !!! At the moment I use very inefficient way
    // !!! to sort elements by several comparators.
    private List<T> sorted(List<T> toSort) {
        // I need to use stable sort.
        // Collections.sort(...) is guaranteed to be stable
        for (Comparator<T> comparator : comparators) {
            Collections.sort(toSort, comparator);
        }
        return toSort;
    }
}

我可以优化sorted() method吗?也许这可以通过使用组合比较器使用单一的集合排序来完成? (而不是用每个比较器多次排序)

(但我必须使用稳定的排序,最后添加的比较器的优先级高于开头添加的比较器)

更新

我使用几个比较器进行排序,按不同的属性对元素进行排序(例如,按优先级,名称等)。

2 个答案:

答案 0 :(得分:6)

问题在于,当您按照自己的方式对其进行排序时,后续排序会完全放弃先前排序所做的排序。

我认为你想要的是说“如果第一个比较器发现它们相等,则按下一个排序”。你可以这样做:

class SomeClass<T> {
    private List<T> elements;
    private List<Comparator<T>> comparators;

    private final Comparator<T> combined = new Comparator<T>() {
        @Override
        public int compare(T e1, T e2) {
            for(Comparator<T> c : comparators) {
                int result = c.compare(e1, e2);

                if(result != 0)
                    return result;
            }

            return 0;
        }
    };

    ...

    private List<T> sorted(List<T> toSort) {
        Collections.sort(toSort, combined);

        return toSort;
    }
}

答案 1 :(得分:5)

使用Guava

static <T> Comparator<T> compound(List<Comparator<T>> comparators)
{
    return Ordering.compound(comparators);
}

给定一对元素,给定列表中的比较器依次尝试,直到一个产生非零结果,返回,或者没有比较器,在这种情况下,零是返回。