[英]Binary search on arrays/comparator using generics Java
I'm struggling to make a comparator for binary search work on an array of objects. 我在努力为对象数组的二进制搜索工作提供一个比较器。 Essentially the goal is to search a ragged array to find the first match of an item OR the closest match to provide an insert point.
本质上,目标是搜索一个参差不齐的数组以找到某项的第一个匹配项,或者找到最接近的匹配项以提供插入点。 The method passes in an generic (this is unchangeable - as this is homework) but you can't create arrays of generic types... so, my comparator is throwing an error: "The method binarySearch(Object[], Object) in type Arrays is not applicable for the arguments (Object[], E, Comparator)".
该方法传入一个泛型(这是不可更改的-因为这是家庭作业),但是您无法创建泛型类型的数组...因此,我的比较器抛出了一个错误:“方法binarySearch(Object [],Object)类型Arrays不适用于参数(Object [],E,Comparator)”。 Perhaps I need to cast the generic element "item"?
也许我需要转换通用元素“ item”? I'm not sure.
我不确定。 Code:
码:
private Location findFirst(E item) {
Location current;
int closestMatchArray1;
int closestMatchArray2;
Object[] firstItemInArray2 = new Object[numArrayInUse];
Object firstItem;
Comparator<E> comparator = new CompareElement();
for (int i - 0; i < numArrayInUse; i++) {
firstItem = topArray[i];
firstItemInArray2[i] = firstItem;
}
closestMatchArray1 = Arrays.binarySearch(firstItemInArray2, item, comparator);
Secondary, but related question. 次要但相关的问题。 In the comparator, I am attempting to invoke the Comparable method "compareTo" to obtain a negative integer that gives an approximate location for where an item would be if it were in the array on a failed search, but again, I'm having trouble with generics, getting this error: "The method compareTo(E) is undefined for the type E".
在比较器中,我尝试调用Comparable方法“ compareTo”以获取一个负整数,该负整数给出一个项目在失败搜索中位于数组中时的大概位置,但是同样,我遇到了麻烦使用泛型时,出现此错误:“类型E的方法compareTo(E)未定义”。 Code:
码:
public class CompareElement implements Comparator<E> {
public int compare(E firstItem, E secondItem) {
return firstItem.compareTo(secondItem);
}
}
I think you either need a Comparator<Object>
or you need an array of E[]
. 我认为您要么需要
Comparator<Object>
要么需要E[]
的数组。 For the latter, I would suggest checking out these two articles: 对于后者,我建议您查看以下两篇文章:
Above reading is encouraged. 鼓励以上阅读。
assumes item is never null 假设item永远不会为null
Based on what I've read in the aforementioned posts, if you know item will never be null
, you could try something like this ... 根据我在上述文章中所读的内容,如果您知道item永远不会为
null
,则可以尝试类似的方法...
@SuppressWarnings("unchecked")
private Location findFirst(E item) {
Location current;
int closestMatchArray1;
int closestMatchArray2;
// Object[] firstItemInArray2 = new Object[numArrayInUse];
// Object firstItem;
E[] firstItemInArray2
= (E[]) Array.newInstance(item.getClass(), numArrayInUse);
E firstItem;
Comparator<E> comparator = new CompareElement();
for (int i = 0; i < numArrayInUse; i++) {
firstItem = (E) topArray[i];
firstItemInArray2[i] = firstItem;
}
closestMatchArray1 = Arrays.binarySearch(firstItemInArray2, item, comparator);
requires Class parameter 需要Class参数
If you can't guarantee the item will never be null
, and you can't provide any special handling for null
values, you could force the Class<?>
parameter to be passed in, as follows... 如果您不能保证该项永远不会为
null
,并且不能对null
值提供任何特殊处理,则可以强制传入Class<?>
参数,如下所示...
@SuppressWarnings("unchecked")
private Location findFirst(E item, Class<E> clazz) {
Location current;
int closestMatchArray1;
int closestMatchArray2;
// Object[] firstItemInArray2 = new Object[numArrayInUse];
// Object firstItem;
E[] firstItemInArray2
= (E[]) Array.newInstance(clazz, numArrayInUse);
E firstItem;
Comparator<E> comparator = new CompareElement();
for (int i = 0; i < numArrayInUse; i++) {
firstItem = (E) topArray[i];
firstItemInArray2[i] = firstItem;
}
closestMatchArray1 = Arrays.binarySearch(firstItemInArray2, item, comparator);
ugly, but it works 丑陋,但是行得通
Alternatively you can create a Comparator<Object>
to wrap your existing Comparator<E>
, as follows (I think it's a bit of a hack, but it works consistently for me) ... 或者,您可以创建一个
Comparator<Object>
来包装现有的Comparator<E>
,如下所示(我认为这有点麻烦,但对我而言始终如一)。
private Location findFirst(E item) {
Location current;
int closestMatchArray1;
int closestMatchArray2;
Object[] firstItemInArray2 = new Object[numArrayInUse];
Object firstItem;
// Comparator<E> comparator = new CompareElement();
Comparator<Object> comparator = new Comparator<Object>() {
private final Comparator<E> delegate = new CompareElement();
@Override
@SuppressWarnings("unchecked")
public int compare(Object o1, Object o2) {
return delegate.compare((E) o1, (E) o2);
}
};
for (int i = 0; i < numArrayInUse; i++) {
firstItem = topArray[i];
firstItemInArray2[i] = firstItem;
}
closestMatchArray1 = Arrays.binarySearch(firstItemInArray2, item, comparator);
Hope this helps! 希望这可以帮助!
You have to pass Class<E>
so you may instantiate an array of E
. 您必须传递
Class<E>
以便可以实例化E
的数组。 (As <E>
is dropped at runtime, E is just Object.) (由于
<E>
在运行时被删除,E只是对象。)
Class<E> klazz;
E[] firstItemInArray2 = (E[])
java.lang.reflect.Arrays.newInstance(klazz, numArraysInUse);
You did not declare <E>
. 您没有声明
<E>
。 You would have to define your CompareElement
as follows: 您必须按如下方式定义
CompareElement
:
public class CompareElement<E extends Comparable> implements Comparator<E> {
public int compare(E firstItem, E secondItem) {
return firstItem.compareTo(secondItem);
}
}
Then declare it as follows: 然后声明如下:
Comparator<?> comparator = new CompareElement<?>();
Whereas ?
而
?
should be the type you want to compare. 应该是您要比较的类型。
Where is your E
declared? 您的
E
在哪里声明? It seems like some type parameter that is declared in some enclosing class that we can't see. 似乎在一些看不到的封闭类中声明了某种类型参数。 It seems that your
CompareElement
class is a comparator that compares elements based on their natural ordering (ie according to Comparable
). 看来您的
CompareElement
类是一个比较器,它根据元素的自然顺序(即,根据Comparable
)比较元素。 If so, then E
must have a bound that guarantees that it is able to compare to itself, <E extends Comparable<? super E>>
如果是这样,则
E
必须具有一个保证能够与自身进行比较的界限, <E extends Comparable<? super E>>
<E extends Comparable<? super E>>
. <E extends Comparable<? super E>>
。 You can change that bound where E
is declared, or, if you want to do it like other people have suggested, to have CompareElement
be parameterized separately from the enclosing class, you would do this: 您可以更改声明
E
边界,或者,如果您想要像其他人所建议的那样进行CompareElement
,以使CompareElement
与封闭类分开进行参数化,则可以这样做:
public class CompareElement<E extends Comparable<? super E>> implements Comparator<E> {
public int compare(E firstItem, E secondItem) {
return firstItem.compareTo(secondItem);
}
}
Your first error is because the version of binarySearch
you're trying to use, the one with a comparator, has restrictions on the types of the arguments. 您的第一个错误是因为您要使用的
binarySearch
版本(带有比较器)对参数类型有限制。 It is declared like this: static <T> int binarySearch(T[] a, T key, Comparator<? super T> c)
. 声明如下:
static <T> int binarySearch(T[] a, T key, Comparator<? super T> c)
。 So If you have a Comparator<E>
, then you will need an E[]
as first parameter, whereas you have an Object[]
. 因此,如果您有
Comparator<E>
,则需要一个E[]
作为第一个参数,而您有一个Object[]
。 You have to think of some way to make it E[]
. 您必须想办法使它成为
E[]
。
But actually for you you're trying to do you don't need to use a comparator at all. 但是实际上,您要尝试执行的操作根本不需要使用比较器。 There is a version of the
binarySearch
method that does not take a comparator, and it already compares elements using their natural ordering. 有一个
binarySearch
方法版本,该版本不使用比较器,它已经使用其自然顺序比较元素。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.