HashSet 添加两个对象,它们 returns 对于 equals() 为真并且在 Java 中具有相同的哈希码
HashSet adds two objects which returns true for equals() and has same hashcode in Java
frequencySet()
正在计算 String
中每个字符的频率 Integer[]
包装到 Counter
class 中,后者已覆盖等号和哈希码。此方法应该 return 仅在集合中出现唯一频率,但会添加两个 Counter
对象。
从打印语句可以看出:hashcode()
returns等于and和equals()
returnstrue
.
怎么了?
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
// your code goes here
String[] a = new String[2];
a[0]="tan";
a[1]="nat";
Set<Counter> s = frequencySet(a);
System.out.println(s.size()); // prints
System.out.println(getFreq(a[0]).equals(getFreq(a[1])) + ":" + getFreq(a[0]).hashcode() + ":" + getFreq(a[1]).hashcode() );
}
public static Set<Counter> frequencySet(String[] strs) {
Set<Counter> set = new HashSet<>();
for(String s: strs){
Counter counter = getFreq(s);
set.add(counter);
//System.out.println(s + " : " + counter.hashcode() + " : " + Arrays.toString(counter.arr) );
}
return set;
}
private static Counter getFreq(String s){
Integer[] frequency = new Integer[26];
for(char c : s.toCharArray()){
Integer a = frequency[c-'a'];
if(frequency[c-'a']==null){
frequency[c-'a']=1;
}
else{
a++;
frequency[c-'a']=a; //++frequency[c-'a'];
}
}
//System
return new Counter(frequency);
}
}
class Counter{
Integer[] arr;
public Counter(Integer[] arr){
this.arr=arr;
}
public int hashcode(){
//return Arrays.deepHashCode((Integer[])arr);
int hashcode=31;
for(int i=0;i<arr.length;i++){
if(arr[i]==null)
hashcode+=i;
else
hashcode+=31*arr[i];
}
return hashcode;
}
public boolean equals(Object o){
//return Arrays.deepEquals(arr,(Integer[])o);
Counter c = (Counter)o;
Integer[] other = c.arr;
for(int i=0;i<26;i++){
if((arr[i]==null && other[i]!=null) || (arr[i]!=null && other[i]==null)){
return false;
}
else if(arr[i]!=null && other[i]!=null && arr[i]!=other[i]){
return false;
}
}
return true;
}
}
输出:
2
true:417:417
<script src="https://ideone.com/e.js/s2LcBw" type="text/javascript" ></script>
您在 hashcode()
中有错字,应该 hashCode()
代替。您可以通过添加 Override
注释来捕获此错误,在这种情况下,编译器将通知您:
@Override
public int hashCode() {
@Override
public boolean equals(Object o) {
始终使用 @Override
。您已实现方法 public int hashcode()
。那不是你想的那样。你想要public int hashCode()
。注意大写字母 c。添加 @Override
注释,编译器会出错(先尝试:@Override public int hashcode()...
,然后编译它,注意错误,通过 hashCode
.
修复它
请注意,您的 hashCode impl 效率极低且很奇怪。您听说过一些关于素数的知识,但没有正确实施。正确的方法是将 哈希码 乘以一个质数(如果必须的话),而不是下一个元素值。
更一般地说,Arrays.deepHashCode
在这里就可以了。我假设这就是发生的事情:
- 您使用 deepHashCode 编写了哈希码实现。
- 代码无效。
- 您(错误地)将 deepHashCode 归咎于罪魁祸首并编写了自己的哈希器。
- 它仍然不起作用 - 合乎逻辑,因为那不是问题所在(问题是用小写字母 c 编写哈希码)。
还原您的 'fix' - 这段带有 deepHashCode 的代码更易于阅读且效率更高。
frequencySet()
正在计算 String
中每个字符的频率 Integer[]
包装到 Counter
class 中,后者已覆盖等号和哈希码。此方法应该 return 仅在集合中出现唯一频率,但会添加两个 Counter
对象。
从打印语句可以看出:hashcode()
returns等于and和equals()
returnstrue
.
怎么了?
class Ideone
{
public static void main (String[] args) throws java.lang.Exception
{
// your code goes here
String[] a = new String[2];
a[0]="tan";
a[1]="nat";
Set<Counter> s = frequencySet(a);
System.out.println(s.size()); // prints
System.out.println(getFreq(a[0]).equals(getFreq(a[1])) + ":" + getFreq(a[0]).hashcode() + ":" + getFreq(a[1]).hashcode() );
}
public static Set<Counter> frequencySet(String[] strs) {
Set<Counter> set = new HashSet<>();
for(String s: strs){
Counter counter = getFreq(s);
set.add(counter);
//System.out.println(s + " : " + counter.hashcode() + " : " + Arrays.toString(counter.arr) );
}
return set;
}
private static Counter getFreq(String s){
Integer[] frequency = new Integer[26];
for(char c : s.toCharArray()){
Integer a = frequency[c-'a'];
if(frequency[c-'a']==null){
frequency[c-'a']=1;
}
else{
a++;
frequency[c-'a']=a; //++frequency[c-'a'];
}
}
//System
return new Counter(frequency);
}
}
class Counter{
Integer[] arr;
public Counter(Integer[] arr){
this.arr=arr;
}
public int hashcode(){
//return Arrays.deepHashCode((Integer[])arr);
int hashcode=31;
for(int i=0;i<arr.length;i++){
if(arr[i]==null)
hashcode+=i;
else
hashcode+=31*arr[i];
}
return hashcode;
}
public boolean equals(Object o){
//return Arrays.deepEquals(arr,(Integer[])o);
Counter c = (Counter)o;
Integer[] other = c.arr;
for(int i=0;i<26;i++){
if((arr[i]==null && other[i]!=null) || (arr[i]!=null && other[i]==null)){
return false;
}
else if(arr[i]!=null && other[i]!=null && arr[i]!=other[i]){
return false;
}
}
return true;
}
}
输出:
2
true:417:417
<script src="https://ideone.com/e.js/s2LcBw" type="text/javascript" ></script>
您在 hashcode()
中有错字,应该 hashCode()
代替。您可以通过添加 Override
注释来捕获此错误,在这种情况下,编译器将通知您:
@Override
public int hashCode() {
@Override
public boolean equals(Object o) {
始终使用 @Override
。您已实现方法 public int hashcode()
。那不是你想的那样。你想要public int hashCode()
。注意大写字母 c。添加 @Override
注释,编译器会出错(先尝试:@Override public int hashcode()...
,然后编译它,注意错误,通过 hashCode
.
请注意,您的 hashCode impl 效率极低且很奇怪。您听说过一些关于素数的知识,但没有正确实施。正确的方法是将 哈希码 乘以一个质数(如果必须的话),而不是下一个元素值。
更一般地说,Arrays.deepHashCode
在这里就可以了。我假设这就是发生的事情:
- 您使用 deepHashCode 编写了哈希码实现。
- 代码无效。
- 您(错误地)将 deepHashCode 归咎于罪魁祸首并编写了自己的哈希器。
- 它仍然不起作用 - 合乎逻辑,因为那不是问题所在(问题是用小写字母 c 编写哈希码)。
还原您的 'fix' - 这段带有 deepHashCode 的代码更易于阅读且效率更高。