为什么Collections.sort使用相同的参数调用Comparator两次?

时间:2016-07-01 02:46:42

标签: java collections comparator comparable

我正在运行一个示例来了解Comparator在Java中的行为。

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;


    class HDTV {
    private int size;
    private String brand;

    public HDTV(int size, String brand) {
        this.size = size;
        this.brand = brand;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }
}

class SizeComparator implements Comparator<HDTV> {
    @Override
    public int compare(HDTV tv1, HDTV tv2) {
        int tv1Size = tv1.getSize();
        int tv2Size = tv2.getSize();
 System.out.println("Comparing :: "+tv1.getBrand()+" AND : "+tv2.getBrand());
        if (tv1Size > tv2Size) {
            return 1;
        } else if (tv1Size < tv2Size) {
            return -1;
        } else {
            return 0;
        }
    }
}

public class HelloWorld {
    public static void main(String[] args) {
        HDTV tv1 = new HDTV(55, "Samsung");
        HDTV tv2 = new HDTV(60, "Sony");
        HDTV tv3 = new HDTV(42, "Panasonic");

        ArrayList<HDTV> al = new ArrayList<HDTV>();
        al.add(tv1);
        al.add(tv2);
        al.add(tv3);

        Collections.sort(al, new SizeComparator());
        for (HDTV a : al) {
            System.out.println(a.getBrand());


        }
        }
    }

输出

  

比较:: Sony AND:Samsung
  比较:: Panasonic AND:Sony
  比较:: Panasonic AND:Sony
  比较:: Panasonic AND:Samsung
  松下
  三星
  索尼

为什么连续2次比较两个对象PanasonicSony? 我发现不需要这样做。

3 个答案:

答案 0 :(得分:2)

如果是Java 7或更高版本,则使用TimSort。 TimSort首先运行输入并检测或收集32个或更多元素的升序(在此实现中)。请参阅源代码中的countRunAndMakeAscending

现在还有超过32的运行。通过对当前运行中的后续元素进行二进制插入排序来延长短于32的运行,直到其长度至少为32个元素。请参阅源代码中的binarySort

(合并排序方法仅在收集&gt; = 32的运行后才完成。由于您的输入只有3个元素,因此整个排序是使用二进制插入排序完成的,并且不进行合并。)

countRunAndMakeAscending要做的是通过比较相邻元素来检测运行。首先,它将索尼与三星,松下与索尼进行比较。结果是长度为2,[三星,索尼]。

接下来,binarySort通过使用下一个元素Panasonic,并将其插入正确的位置来延长此次运行。进行二分查找以找到该位置。 2的运行中点是位置1,这是索尼,因此它将松下与索尼进行比较。 (这是重复的比较。)松下比索尼少,所以下一个比较是在松下和三星之间,这决定了正确的插入点。我们现在有一个长度为3的运行。

由于整个输入的长度为3,因此在四次比较后完成排序。

重复比较的发生是因为countRunAndMakeAscendingbinarySort是单独的排序阶段,并且恰好第一阶段的最后一次比较与第二阶段的第一次比较相同。 / p>

答案 1 :(得分:1)

排序算法是一个复杂的主题。考虑这个非常简单(但效率低下)的算法。

将第一项与第二项进行比较。跟踪较高的项目并将其与下一项目进行比较。跟踪最高项目,直到到达列表末尾以查找列表中的最高项目。将最高的一个放在新列表中,然后将其从原始列表中删除。

然后重复前面的步骤,直到原始列表为空。

因为您要多次浏览列表,所以最终可能会多次将项目与其邻居进行比较。也许甚至连续不同的传球。

答案 2 :(得分:1)

它取决于排序算法,它调用比较方法的次数。一旦我们调用Collections.sort()方法,它就会转到Collections.sort()中使用的排序实现。

Collections.sort()实现使用合并排序。根据Javadoc,只使用Quicksort对原始数组进行排序。对象数组也使用Mergesort进行排序。