1

オブジェクトの配列でバイナリ検索のコンパレータを作成するのに苦労しています。基本的に、目標は、不規則な配列を検索して、アイテムの最初の一致または最も近い一致を見つけて、挿入ポイントを提供することです。メソッドはジェネリックを渡します (これは変更できません - これは宿題です) が、ジェネリック型の配列を作成することはできません... そのため、私のコンパレーターはエラーをスローしています: "メソッド binarySearch(Object[], Object) in type Arrays は、引数 (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」を呼び出して、検索に失敗した場合に項目が配列内にあった場合のおおよその位置を示す負の整数を取得しようとしていますが、やはり問題が発生しています。ジェネリックを使用すると、「メソッドcompareTo(E)はタイプ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[]。後者については、次の 2 つの記事をチェックすることをお勧めします。

上記をお読みになることをお勧めします。


オプション 1: Array.newInstance()

item が null にならないことを前提としています

前述の投稿で私が読んだことに基づいて、アイテムが決して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()

Class パラメータが必要です

アイテムが決して にならないことを保証できず、値に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>(少しハックだと思いますが、私にとっては一貫して機能します) ...

    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次のように定義する必要があります。

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 に答える
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[]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 に答える