1

我正在努力使二进制搜索的比较器在对象数组上工作。本质上,目标是搜索参差不齐的数组以找到项目的第一个匹配项或最接近的匹配项以提供插入点。该方法传入一个泛型(这是不可更改的 - 因为这是家庭作业),但你不能创建泛型类型的数组......所以,我的比较器抛出一个错误:“方法 binarySearch(Object[], Object) in类型数组不适用于参数 (Object[], E, Comparator)”。也许我需要转换通用元素“项目”?我不确定。代码:

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);

次要但相关的问题。在比较器中,我试图调用 Comparable 方法“compareTo”来获取一个负整数,该整数给出了一个项目在失败搜索时位于数组中的大致位置,但同样,我遇到了麻烦使用泛型,出现此错误:“未定义类型 E 的方法 compareTo(E)”。代码:

public class CompareElement implements Comparator<E> {
  public int compare(E firstItem, E secondItem) {
     return firstItem.compareTo(secondItem);
  }
}
4

4 回答 4

1

我认为您要么需要一个,要么需要Comparator<Object>一个E[]. 对于后者,我建议查看这两篇文章:

鼓励阅读以上内容。


选项 1:Array.newInstance()

假设 item 永远不会为空

根据我在上述帖子中读到的内容,如果您知道 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);

选项 2:Array.newInstance()

需要类参数

如果不能保证 item 永远不会是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);

选项 3:对象比较器包装器

丑陋,但它有效

或者,您可以创建一个Comparator<Object>来包装您现有的Comparator<E>,如下所示(我认为这有点像 hack,但它对我来说始终如一)......

    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);

希望这可以帮助!

于 2013-09-12T18:24:56.557 回答
0

你在哪里E申报的?看起来像是在我们看不到的某个封闭类中声明的某些类型参数。您的类似乎CompareElement是一个比较器,它根据元素的自然顺序(即根据Comparable)比较元素。如果是这样,则E必须有一个边界来保证它能够与自身进行比较,<E extends Comparable<? super E>>。您可以更改声明的边界E,或者,如果您想像其他人建议的那样做,CompareElement与封闭类分开参数化,您可以这样做:

public class CompareElement<E extends Comparable<? super E>> implements Comparator<E> {
  public int compare(E firstItem, E secondItem) {
     return firstItem.compareTo(secondItem);
  }
}

您的第一个错误是因为binarySearch您尝试使用的版本(带有比较器的版本)对参数的类型有限制。它是这样声明的:static <T> int binarySearch(T[] a, T key, Comparator<? super T> c). 因此,如果您有一个Comparator<E>,那么您将需要一个E[]as 第一个参数,而您有一个Object[]. 你必须想办法做到E[]

但实际上对你来说,你正在尝试做你根本不需要使用比较器。该方法有一个版本binarySearch不使用比较器,并且它已经使用元素的自然顺序来比较元素。

于 2012-10-12T01:18:21.873 回答
0

你必须通过Class<E>,所以你可以实例化一个E. (<E>在运行时删除,E 只是对象。)

Class<E> klazz;

E[] firstItemInArray2 = (E[])
        java.lang.reflect.Arrays.newInstance(klazz, numArraysInUse);
于 2012-10-11T14:04:28.527 回答
0

你没有申报<E>。您必须将您的定义CompareElement如下:

public class CompareElement<E extends Comparable> implements Comparator<E> {
    public int compare(E firstItem, E secondItem) {
        return firstItem.compareTo(secondItem);
    }
}

然后声明如下:

Comparator<?> comparator = new CompareElement<?>();

?应该是您要比较的类型。

于 2012-10-11T14:14:24.850 回答