Java HashSet 包含函数不工作
Java HashSet contains function not working
我正在写一个简单的程序如下:给定两个数M和N,p来自[M,N],q来自[1,p-1],找到[=21=的所有不可约分数].
我的想法是暴力破解 p、q 的所有可能值。并使用 HashSet 来避免重复分数。但是,不知何故 contains 函数没有按预期工作。
我的代码
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);
}
}
这是程序的输出
4/3
3/1
4/1
2/1
3/2
2/1
你可以看到分数 2/1 是重复的。任何人都可以帮助我弄清楚为什么以及如何解决它。
非常感谢。
你需要实现Fraction#equals()
和Fraction#hashcode()
,因为那是用来判断集合是否包含特定值的天气。没有它,将比较对象引用,这不会给你想要的结果。
覆盖 Fraction
class 中的 Object#equals
和 Object#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
class 不会覆盖 hashCode
和 equals
。 HashMap
包含尝试查找与您提供的哈希码相同(且等于)的键。当您创建 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;
}
我正在写一个简单的程序如下:给定两个数M和N,p来自[M,N],q来自[1,p-1],找到[=21=的所有不可约分数]. 我的想法是暴力破解 p、q 的所有可能值。并使用 HashSet 来避免重复分数。但是,不知何故 contains 函数没有按预期工作。
我的代码
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);
}
}
这是程序的输出
4/3
3/1
4/1
2/1
3/2
2/1
你可以看到分数 2/1 是重复的。任何人都可以帮助我弄清楚为什么以及如何解决它。 非常感谢。
你需要实现Fraction#equals()
和Fraction#hashcode()
,因为那是用来判断集合是否包含特定值的天气。没有它,将比较对象引用,这不会给你想要的结果。
覆盖 Fraction
class 中的 Object#equals
和 Object#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
class 不会覆盖 hashCode
和 equals
。 HashMap
包含尝试查找与您提供的哈希码相同(且等于)的键。当您创建 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;
}