Java哈希集包含无法工作的函数

Java哈希集包含无法工作的函数,java,hash,hashcode,hashset,Java,Hash,Hashcode,Hashset,我正在写一个简单的程序如下:给定两个数M和N,p来自[M,N],q来自[1,p-1],求p/q的所有不可约分数。 我的想法是蛮力,p,q的所有可能值。使用HashSet避免重复分数。但是,不知何故,该函数包含的函数没有按预期工作 我的代码 import java.util.HashSet; import java.util.Set; public class Fraction { private int p; private int q; Fraction(int p

我正在写一个简单的程序如下:给定两个数M和N,p来自[M,N],q来自[1,p-1],求p/q的所有不可约分数。 我的想法是蛮力,p,q的所有可能值。使用HashSet避免重复分数。但是,不知何故,该函数包含的函数没有按预期工作

我的代码

import java.util.HashSet;
import java.util.Set;

public class Fraction {
    private int p;
    private int q;

    Fraction(int p, int q) {
        this.p = p;
        this.q = q;
    }

    public static int getGCD(int a, int b) {
        if (b == 0)
            return a;
        else 
            return getGCD(b, a % b);
    }

    public static Fraction reduce(Fraction f) {
        int c = getGCD(f.p, f.q);
        return new Fraction(f.p / c, f.q / c);
    }

    public static HashSet<Fraction> getAll(int m, int n) {
        HashSet<Fraction> res = new HashSet<Fraction>();
        for (int p = m; p <= n; p++)
            for (int q = 1; q < p; q++) {
                Fraction f = new Fraction(p,q);
                Fraction fr = reduce(f);
                if (!res.contains(fr))
                    res.add(fr);
            }
        return res;
    }

    public static void print(Fraction f) {
        System.out.println(f.p + "/" + f.q);
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        HashSet<Fraction> res = getAll(2, 4);
        for (Fraction f : res)
            print(f);
    }

}
你可以看到分数2/1是重复的。任何人都可以帮我找出原因和解决方法。
非常感谢。

您需要实现
分数等于()
分数hashcode()
,因为这用于确定集合是否包含特定值。如果没有它,将比较对象引用,这将不会给出所需的结果。

覆盖
分数
类中的
对象#equals
对象#hashCode
方法。
HashSet
使用这些方法来确定两个对象是否相同。如果不重写它们,equals方法将测试对象引用的相等性,而不是其字段值的相等性

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + p;
    result = prime * result + q;
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Fraction other = (Fraction) obj;
    if (p != other.p)
        return false;
    if (q != other.q)
        return false;
    return true;
}

您的
Fraction
类不会重写
hashCode
equals
HashMap
contains尝试查找与您提供的hashCode相同(等于)的键。创建
Fraction
的新实例时,它将永远不会与
HashMap
中已有的实例相同。下面是如何执行
hashCode
equals

@Override
public int hashCode() {
    return super.hashCode() + p * 24 + q * 24;
}

@Override
public boolean equals(Object other) {
    if (!(other instanceof Fraction)) return false;
    return ((Fraction) other).p == this.p && ((Fraction) other).q == this.q;
}

让我们不要忘记
hashCode()
方法:我只想补充一点,这些函数通常可以由IDE自动实现,而无需编写代码。除非您想要有一个特定的行为,否则IDE提供的行为通常在大多数情况下就足够了。@ordago,没错,上面的实现是由Eclipse自动生成的
@Override
public int hashCode() {
    return super.hashCode() + p * 24 + q * 24;
}

@Override
public boolean equals(Object other) {
    if (!(other instanceof Fraction)) return false;
    return ((Fraction) other).p == this.p && ((Fraction) other).q == this.q;
}