首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

Java ArrayList 去重邏輯陷阱:同一物件引用導致無限迴圈

     編輯:程式設計疑難解答

問題重現

List<Rational> list = new ArrayList<>();
Rational r = new Rational(); // 單一實例
for (int i = 0; i < 10; i++) {
    do {
        r.denominator = random.nextInt(...);
        r.numerator = random.nextInt(...);
    } while (list.contains(r)); // 永遠比較同一物件
    list.add(r); // 列表裡全是同一個引用
}

核心原因

  • contains() 預設呼叫 equals()。若 Rational 未覆寫 equals()/hashCode(),則比較的是**記憶體位址**。
  • 迴圈中不斷修改同一個 Rational 實例的欄位,列表中儲存的全是指向該實例的引用,導致 contains() 永遠返回 true(第一次加入後),進入無限迴圈。

正確寫法

for (int i = 0; i < 10; i++) {
    Rational r; // 每次迴圈新建實例
    do {
        int d = random.nextInt(...);
        int n = random.nextInt(...);
        r = new Rational(n, d); // 新物件
    } while (list.contains(r)); // 需 Rational 正確實作 equals/hashCode
    list.add(r);
}

必要條件:覆寫 equals() 與 hashCode()

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof Rational)) return false;
    Rational that = (Rational) o;
    return numerator == that.numerator && denominator == that.denominator;
}

@Override
public int hashCode() {
    return Objects.hash(numerator, denominator);
}

若不想覆寫,可改用 Set<Rational> 並提供自訂 Comparator,或將分子分母組合成字串存入 Set<String> 去重。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved