Java实现PriorityQueue - 当没有提供Comparator时

时间:2014-01-16 03:54:21

标签: java priority-queue comparator

我正在尝试在Java中实现我自己的通用PriorityQueue版本(使用二进制堆)。我选择为我的堆使用Object数组。

Object[] qArray = new Object[initial_Size];

如果用户提供比较器 - 实现非常简单,因为我在进行元素比较时可以使用比较器的比较方法。

Comparator<T> comparator; //Set to a user-provided comparator in my constructor.

if(comparator.compare((T)qArray[i], (T)qArray[j])
    //do something

然而,当用户没有提供默认比较器时会出现问题。我可以解决这个问题的一种方法是让我的PriorityQueue类实现Comparator并让比较器执行以下比较 -

@Override
public int compare(T o1, T o2)
{
    if(this.comparator == null) //no comparator provided by user
    {
        return o1.toString().compareTo(o2.toString());
    }
    else
    {
        return this.comparator.compare(o1, o2);
    }
}

然而,这个比较器有点蹩脚。对于String类型的PriorityQueues来说,它显然效果很好,但是在(比方说)整数的情况下,并不完全(它会认为5大于49)。另一种方法是强制用户提供比较器 - 但我知道Java Util的PriorityQueue实现更加友好。

因此,我尝试对Java的PriorityQueue进行一些反向工程,并初始化了一个自定义类类型的优先级队列而不传入比较器。

public class TestClass {

    public class SomeClass
    {
        int value;
        SomeClass(int value)
        {
            this.value = value;
        }
    }

    public static void main(String[] args)
    {
        TestClass tClass = new TestClass();
        TestClass.SomeClass sClass1 = tClass.new SomeClass(10);
        TestClass.SomeClass sClass2 = tClass.new SomeClass(20);

        PriorityQueue<TestClass.SomeClass> pQueue = new PriorityQueue<TestClass.SomeClass>();
        pQueue.add(sClass1);
    }
}

StackTrace

因此,这个siftUpComparable方法可能包含一些关于util包如何进行比较的重要线索,但是当我尝试读取源代码时,我丢失了。

所以这里有任何实现的想法 - 其中如果在提供的对象类型(如Integer或String)上定义了自然排序比较器,则默认情况下应该使用它。

2 个答案:

答案 0 :(得分:2)

异常揭示了一切:如果你没有提供Comparable,Java会尝试将给定对象强制转换为Comparator

您不能只使用通用算法比较任意类型的对象。这正是您必须提供Comparator或确保您的对象支持compareTo方法并实施Comparable的原因。

答案 1 :(得分:1)

由于你没有传递 Comparator SomeClass应该实现Comparable接口,即

public class SomeClass implements Comparable<Integer>
{
    int value;
    SomeClass(int value)
    {
        this.value = value;
    }
    public int compareTo(Integer o) {
        ....... // Logic to compare
    }
}