3

オブジェクトのJavaコレクションを整数値「レベル」でソートする必要があります。また、このコレクションにすでに「タイトル」でオブジェクトが含まれているかどうかを判断する必要があります。

コレクションの最良の選択は、一意の値の順序セットを持つTreeSetであると思います。

「level」属性と「title属性」を持つオブジェクトがあります。次のように同等の実装を行います。

これは、Equalsメソッドをオーバーライドします(オブジェクトが「title」によってTreeSetにすでに含まれているかどうかを確認するため)。

コードは次のようになります。

@Override
public boolean equals(Object arg0) {

    Artifact obj = (Artifact) arg0;

    if (this.getTitle().equals(obj.getTitle())) { 
        return true;
    }

    return false;
}

@Override
public int compareTo(Artifact aThat) {  

    final int BEFORE = -1;
    final int EQUAL = 0;
    final int AFTER = 1;

    if (this == aThat) return EQUAL;

    if (this.level < aThat.level) return BEFORE;
    if (this.level > aThat.level) return AFTER;

    assert this.equals(aThat) : "compareTo inconsistent with equals.";
    return EQUAL;
}

重複する可能性のある値を持つ配列リストからリストに値を追加しようとしたとき。含むは機能していないようで、オブジェクトは関係なくTreeSetに追加されます。コードは次のとおりです。

TreeSet<Artifact> subsetOfArtifacts = new TreeSet<Artifact>();

ArrayList<Artifact> allArtifacts = getArtifacts(); 
Iterator<Artifact> allArtifactsIter = allArtifacts.iterator();

while (allArtifactsIter.hasNext()) {
    Artifact artifact = (Artifact) allArtifactsIter.next();
    if (!subsetOfArtifacts.contains(artifact)) {
        subsetOfArtifacts.add(artifact);
    }
 }

理想的には、すべての固有のアーティファクトのリストをレベル別にソートしたいと思います。どうすればこれを達成できますか?

4

4 に答える 4

3

オーバーライドする場合は、オーバーライドequals()する必要がありますhashCode()。それ以外の場合、コレクション、特にセットの動作は定義されていません。次のメソッドをクラスに追加する必要があります。

@Override
public int hashCode() {
    return title.hashCode();
}

次に、代わりにHashSetを使用Set sortedSet = new TreeSet(set);して、並べ替えに使用する必要があります。これを行うと、すべて正常に機能するはずです。

その理由は、HashTablesは、2つのオブジェクトが同じでequal()ある場合、それらhashCode()も等しいという事実に依存しているためです。これは、javadocからの抜粋です。hashCode()

hashCodeの一般的なコントラクトは次のとおりです。

  • Javaアプリケーションの実行中に同じオブジェクトで複数回呼び出される場合は常に、オブジェクトのequals比較で使用される情報が変更されていない限り、hashCodeメソッドは一貫して同じ整数を返す必要があります。この整数は、アプリケーションのある実行から同じアプリケーションの別の実行まで一貫している必要はありません。
  • equals(Object)メソッドに従って2つのオブジェクトが等しい場合、2つのオブジェクトのそれぞれでhashCodeメソッドを呼び出すと、同じ整数の結果が生成される必要があります。
  • equals(java.lang.Object)メソッドに従って2つのオブジェクトが等しくない場合、2つのオブジェクトのそれぞれでhashCodeメソッドを呼び出すと、異なる整数の結果が生成される必要はありません。ただし、プログラマーは、等しくないオブジェクトに対して個別の整数結果を生成すると、ハッシュテーブルのパフォーマンスが向上する可能性があることに注意する必要があります。
于 2012-05-09T23:37:58.130 に答える
1

レベルを比較するためにcompareToが必要なだけでなく、equalsがタイトルを比較するため、タイトルを比較するためにも必要です。

public int compareTo(Artifact aThat) {

    final int BEFORE = -1;
    final int EQUAL = 0;
    final int AFTER = 1;

    if ( this == aThat ) return EQUAL;

    if (this.level < aThat.level) return BEFORE;
    if (this.level > aThat.level) return AFTER;
    return this.getTitle().compareTo(aThat.getTitle());

//        assert this.equals(aThat) : "compareTo inconsistent with equals.";

//    return EQUAL;
}

また、ボヘミアンが言及しているように、equals()をオーバーライドする場合は、hashCode()をオーバーライドする必要がありますが、TreeSetで重複アイテムを追加できるのはそのためではありません。

于 2012-05-09T23:37:28.620 に答える
0

TreeSetのRTFM:D javadocは、「セットによって維持される順序(明示的なコンパレータが提供されているかどうかに関係なく)は、セットインターフェイスを正しく実装するためにequalsと一致している必要があることに注意してください」

イコールとコンパレータに一貫性がありません。追加する必要があるものを並べ替える必要があります。

ユースケースに合わせて独自の実装を作成する必要がある場合があります

そして他の人が言ったように:あなたが等号を変更する場合は、常にハッシュコードを変更してください。

2つの等しいオブジェクトは、等しいハッシュコードを生成する必要があります。

于 2012-05-09T23:53:30.663 に答える
0

compareToは、最初にレベル、次にタイトルをチェックする必要があります。最初にレベル、次にタイトルでソートし、レベルとタイトルの両方が等しい場合にのみ等しいを返します。このようなもの:

@Override
public int compareTo(Artifact aThat) 
{
    final int BEFORE = -1;
    final int EQUAL = 0;
    final int AFTER = 1;

    if ( this == aThat ) return EQUAL;

    if( this.level < aThat.level ) return BEFORE;
    if( this.level > aThat.level ) return AFTER;

    int compare = this.getTitle().compareTo(aThat.getTitle());

    if( compare != EQUAL ) return compare;

    assert this.equals(aThat) : "compareTo inconsistent with equals.";

    return EQUAL;
}

投稿する前にロブの答えを見ませんでした。

于 2012-05-09T23:59:41.280 に答える