-1

以下が機能しない理由を誰かに説明してもらえますか (滑走路は Hibernate PersistentSet です)。

System.out.println("size before " + runways.size());
Iterator<Runway> deleteIterator = runways.iterator();
while (deleteIterator.hasNext()) {
    Runway rwy = deleteIterator.next();
    if (rwy == rwy3) {
        System.out.println("remove !");
        deleteIterator.remove();
    }
}
System.out.println("size after " + runways.size());

system.Out ログを取得します。

INFO: size before 3
INFO: remove !
INFO: size after 3

イテレータによる削除は安全で可能だと思いました。ログ「削除」が表示されます。remove() メソッドが呼び出されたことを示します。

EDIT : PersistentSet には、Iterator インターフェイスからの remove メソッドに問題があります。

4

4 に答える 4

3

//編集: 参考までに、このコードは失敗したコードの例です。equals()and をhashCode()適切にオーバーライドします。

JustinKSU の指摘をフォローアップするには、and をうまく実装しないhashCode()equals()、あなたがしていることはうまくいきません。equals()と を汚すと、あなたの状況を再現できますhashCode()

public static void main(String[] args) {
    Set<Runway> runways = new HashSet<Runway>();
    Runway rwy1 = new Runway();
    Runway rwy2 = new Runway();
    Runway rwy3 = new Runway();
    runways.add(rwy1);
    runways.add(rwy2);
    runways.add(rwy3);
    System.out.println("size before " + runways.size());
    Iterator<Runway> deleteIterator = runways.iterator();
    while (deleteIterator.hasNext()) {
        Runway rwy = deleteIterator.next();
        if (rwy == rwy3) {
            System.out.println("remove !");
            deleteIterator.remove();
        }
    }
    System.out.println("size after " + runways.size());
}

private static class Runway {
    @Override
    public boolean equals(Object obj) {
        return false;
    }

    @Override
    public int hashCode() {
        return (new Random()).nextInt();
    }
}
于 2013-05-01T16:33:25.713 に答える
0

JDK ソース コード (ここで見つけました) を見ると、a によって返されるイテレータは、実際の削除を実行するために の内部 remove メソッドのHashSet1 つを使用します。HashSet

aHashSetが正しく機能するためには、クラス内でequalsとの両方をそのままにしておくか、両方をオーバーライドする必要があります。この SO の質問では、この問題について説明しています: Java で equals と hashCode をオーバーライドするときに考慮すべき問題は何ですか?hashCodeRunway

于 2013-05-01T16:47:34.950 に答える
0

私の equals メソッドと hashCode メソッドは、Eclipse 自体によって作成されました。だからそれは彼らから来ていません。

しかし、私は質問の冒頭で速すぎました。Runways が Hibernate の PersistentSet であることを忘れていました (java.util.HashSet ではありません)。

PersistenSet イテレーターからオブジェクトを削除できない理由を説明するこのバグを見つけました。

バグは古く、解決が複雑なようです。私の唯一のオプションは、最初のセットからセットを再作成することであり、必要のない要素はありません。

于 2013-05-01T16:56:12.133 に答える