简体   繁体   English

为什么compareTo方法在排序对象数组时这么慢

[英]Why is compareTo method so slow when sorting an array of objects

I have an array of Entry objects (its part of a solution to create a basic phone directory) - each Entry object containing three fields (which is the data of the phone directory) public String surname; public String initial; public String number; 我有一个Entry对象数组(它是创建基本电话目录的解决方案的一部分) - 每个Entry对象包含三个字段(这是电话目录的数据) public String surname; public String initial; public String number; public String surname; public String initial; public String number;

Initially, when adding these to an array (I know an array is NOT a good choice of data structure for something like phone directory, but it was in the specification), after the addition of each entry, it was sorted - the idea being that as the java library sort uses a hybrid Timsort which looks for runs of already sorted data, it would be nearly as fast, and a lot simpler, than inserting the entry into the correct location and than directly inserting the new Entry into the correct location. 最初,当将这些添加到数组时(我知道数组不是电话目录之类的数据结构的一个很好的选择,但它在规范中),在添加每个条目之后,它被排序 - 这个想法是因为java库排序使用混合Timsort来查找已经排序的数据的运行,所以它比将条目插入正确的位置并且直接将新条目插入正确的位置几乎一样快且简单得多。

The sort method ran as follows sort方法运行如下

protected void sort() {

    /*
     * Uses comparator because else it fails to sort the null values to the end of the array, and
     * throws null pointer exception instead
     */

    Arrays.sort(this.directory, new Comparator<Entry>() {
        public int compare(Entry entry1, Entry entry2) {
            if (entry1 == null) { // if entries are null will sort to back of
                                // array
                return 1;
            }

            if (entry2 == null) {
                return -1;
            }

            return entry1.surname.compareTo(entry2.surname); //NB this line
        }

    });
}

However, it was pointed out to me that, interacting directly with the fields of another object was bad style (which makes sense!). 然而,有人向我指出,直接与另一个对象的字段交互是坏的风格(这是有道理的!)。 and so the line marked above was replaced with return entry1.surname.compareTo(entry2.surname); 所以上面标记的行被替换为return entry1.surname.compareTo(entry2.surname);

This means it uses the compareTo method from the entry class. 这意味着它使用条目类中的compareTo方法。 However - for some reason which I don't understand - this slows it down MASSIVELY. 然而 - 由于某些我不理解的原因 - 这会慢慢减少它。 It goes from being able to add 3000 entries in a second to taking over 30 seconds - considering the compareTo method below, WHY does it take so long? 它可以在一秒钟内添加3000个条目到超过30秒 - 考虑到下面的compareTo方法,为什么需要这么长时间?

    @Override
public int compareTo(Entry o) {

    if (this.getClass() == null) {
        return -1;
    }

    if (o == null) {
        return 1;
    }

    if (this.surname.equalsIgnoreCase(o.surname)) {
        return this.initial.compareToIgnoreCase(o.initial);
    }

    return this.surname.compareToIgnoreCase(o.surname);

}

Your tie resolution logic is inverted: instead of comparing surnames for equality upfront, compare them with compareToIgnoreCase first, and check the result for zero. 您的联系解析逻辑是反转的:不是先将先前的等式与姓氏进行比较,而是首先将它们与compareToIgnoreCase进行比较,然后将结果检查为零。 Otherwise, you are effectively doing the comparison twice: 否则,您实际上两次进行比较:

int res = this.surname.compareToIgnoreCase(o.surname);
return res != 0 ? res : this.initial.compareToIgnoreCase(o.initial);

Assuming a small number of ties, this should speed up your comparisons about twofold. 假设少数关系,这应该加快你的双重比较。

In addition, your code has other inefficiencies: for example, it is pointless to null check the result of this.getClass() , because it is never null . 此外,您的代码还有其他低效率:例如,null检查this.getClass()的结果是没有意义的,因为它永远不会为null

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM