我正在尝试在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);
}
}
因此,这个siftUpComparable方法可能包含一些关于util包如何进行比较的重要线索,但是当我尝试读取源代码时,我丢失了。
所以这里有任何实现的想法 - 其中如果在提供的对象类型(如Integer或String)上定义了自然排序比较器,则默认情况下应该使用它。
答案 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
}
}