我的自定义类将由HashSet包含
public class Person {
String name;
int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"hashcode='" + this.hashCode() + '\'' +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Person)) return false;
Person person = (Person) o;
if (age != person.age) return false;
if (!name.equals(person.name)) …Run Code Online (Sandbox Code Playgroud) 决定在java.lang.Object中包含这些方法的原因是什么?对于许多类来说,平等和散列是没有意义的.
制作两个接口更合乎逻辑:
interface Equalable {
boolean equals(Equalable other);
}
interface Hashable extends Equalable {
int hashCode();
}
Run Code Online (Sandbox Code Playgroud)
例如,HashSet定义可能看起来像
class HashSet<T extends Hashable> ...
Run Code Online (Sandbox Code Playgroud)
它可以防止常见的初学者错误之一 - 使用一组项而不实现equals/hashCode.
Hashcode()和equals()的概念是
1)如果两个对象根据equal()相等,则在这两个对象中的每一个上调用hashcode方法应该产生相同的哈希码.
而另一个是
2)如果两个对象根据equal()不相等,则不需要在两个对象中的每一个上调用hashcode方法必须产生不同的值.
我尝试并理解了第一个,这是第一点的代码.
public class Test {
public static void main(String[] args) {
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
map.put(1, 11);
map.put(4, 11);
System.out.println(map.hashCode());
Map<Integer, Integer> map1 = new HashMap<Integer, Integer>();
map1.put(1, 11);
map1.put(4, 11);
System.out.println(map1.hashCode());
if (map.equals(map1)) {
System.out.println("equal ");
}
}
}
Run Code Online (Sandbox Code Playgroud)
上面的程序为两个不同的对象提供相同的哈希码.
有人可以用一个例子来解释我,根据equals()不同的两个不同对象如何具有相同的哈希码.
我在C#中有一个Address类,如下所示:
public class Address
{
public string StreetAddress { get; set; }
public string RuralRoute { get; set; }
public string City { get; set; }
public string Province { get; set; }
public string Country { get; set; }
public string PostalCode { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我正在实现相等性,所以我需要覆盖哈希码.起初我打算使用EJ的哈希码公式,但后来我想:这些都是字符串字段,我不能只使用StringBuilder连接它们并从该字符串返回哈希码?
那是:
var str = new StringBuilder();
str.Append(StreetAddress)
.Append(RuralRoute)
...
return str.ToString().GetHashCode();
Run Code Online (Sandbox Code Playgroud)
这有什么优点/缺点?我为什么不这样做?
我正在阅读Joshua Bloch的Effective Java 第3章.在第8项:覆盖equals时始终覆盖hashCode,作者在其散列函数中使用以下组合步骤:
result = 37 * result + c;
Run Code Online (Sandbox Code Playgroud)
然后他解释了为什么选择了37(强调添加):
选择乘法器37是因为它是奇数素数.如果它是偶数并且乘法溢出,则信息将丢失,因为乘以2相当于移位.使用素数的优点不太清楚,但为此目的使用素数是传统的.
我的问题是为什么组合因子(37)是奇数是重要的?不管乘数是奇数还是偶数,乘法溢出都不会导致信息丢失?
当我们有equals(),compareTo()方法为什么hashcode()在Java中有一个方法?
如果我们使用 HashTable我们必须覆盖hashcode()方法,除快速访问随机密钥有什么特殊原因吗?如果我们覆盖该hashcode()方法,可能的实现是什么?
Java如何确保内存中的对象唯一性?
Hashcodes are typically used to enhance the performance of large collections of data.
在hashing我们计算hash code.这是一项额外的任务.当我们为添加到集合的每个对象执行其他操作时.性能如何提高?
我已经用Netbeans开发了一段时间的Java,并且有些事情我只是依赖于工作而没有真正质疑如何.其中包括自动生成的hashCode()和equals()方法.
equals方法很容易遵循,但我发现hashCode方法有些神秘.我不明白为什么它选择乘数并应用它所做的操作.
import java.util.Arrays;
import java.util.Objects;
public class Foo {
int id;
String bar;
byte[] things;
@Override
public int hashCode() {
int hash = 7;
hash = 89 * hash + this.id;
hash = 89 * hash + Objects.hashCode(this.bar);
hash = 89 * hash + Arrays.hashCode(this.things);
return hash;
}
}
Run Code Online (Sandbox Code Playgroud)
搜索文档,这个网站和谷歌搜索"netbeans生成哈希码"之类的内容,似乎没有任何相关内容.有谁在这里熟悉这一代策略是什么以及为什么Netbeans使用它?
编辑:
感谢您的答案到目前为止!特别是由于对链接的SO问题的这个答案,我理解现在更充分地使用素数来设计hashCode方法的逻辑.然而,到目前为止我没有真正解决的问题的另一个方面是Netbeans如何以及为什么选择它为其生成的方法所做的素数.的hash字段,另一个乘法器(89在我的例子)似乎取决于类的各种因素是不同的.
例如,如果我String在类中添加第二个,则hashCode()变为
public int hashCode() {
int hash = 7;
hash = 13 * hash + this.id;
hash = 13 …Run Code Online (Sandbox Code Playgroud) 我很想知道Java和Scala如何在字符串上实现切换:
class Java
{
public static int java(String s)
{
switch (s)
{
case "foo": return 1;
case "bar": return 2;
case "baz": return 3;
default: return 42;
}
}
}
Run Code Online (Sandbox Code Playgroud)
object Scala {
def scala(s: String): Int = {
s match {
case "foo" => 1
case "bar" => 2
case "baz" => 3
case _ => 42
}
}
}
Run Code Online (Sandbox Code Playgroud)
看起来Java会切换哈希码,然后进行单个字符串比较:
0: aload_0
1: dup
2: astore_1
3: invokevirtual #16 // Method java/lang/String.hashCode:()I
6: lookupswitch { // 3 …Run Code Online (Sandbox Code Playgroud) 我最近将我的一个项目从.NET Core 2.0升级到.NET Core 2.1.这样做后,我的几个测试开始失败.
在缩小此范围之后,我发现在.NET Core 2.1中,使用带有文化感知的比较器和字符串排序比较选项来计算字符串的哈希码是不可能的.
我创建了一个可以重现我的问题的测试:
[TestMethod]
public void Can_compute_hash_code_using_invariant_string_sort_comparer()
{
var compareInfo = CultureInfo.InvariantCulture.CompareInfo;
var stringComparer = compareInfo.GetStringComparer(CompareOptions.StringSort);
stringComparer.GetHashCode("test"); // should not throw!
}
Run Code Online (Sandbox Code Playgroud)
我在几个框架上测试了它,结果如下:
失败的时候ArgumentException会CompareInfo.GetHashCodeOfString说:
标志的值无效
现在,我的问题:
为什么CompareOptions.StringSort在计算哈希码时不允许使用它?
为什么在.NET Core 2.0中允许它?`
据我所知,CompareOptions.StringSort只影响字符串的相对排序顺序,不应影响哈希码计算.MSDN说:
StringSort指示字符串比较必须使用字符串排序算法.在字符串排序中,连字符和撇号以及其他非字母数字符号位于字母数字字符之前.
我正在写一个类Vec2D,代表一个二维向量.我存储x和y在double秒.
当被要求生成equals(Object obj并且hashCode(),eclipse生成了这个:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
long temp;
temp = Double.doubleToLongBits(x);
result = prime * result + (int) (temp ^ (temp >>> 32));
temp = Double.doubleToLongBits(y);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null) …Run Code Online (Sandbox Code Playgroud)