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);
}
@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> 去重。