您需要为记录重写hashCode()和equals()吗



假设以下示例:

public record SomeRecord(int foo, byte bar, long baz)
{ }

如果要将所述对象添加到HashMap,是否需要覆盖hashCodeequals

不需要定义自己的hashCodeequals。如果您希望覆盖默认实现,则可以执行此操作。

详见本规范第8.10.3节https://docs.oracle.com/javase/specs/jls/se14/preview/specs/records-jls.html#jls-8.10

特别要注意的是,在实现自己版本的时需要注意的事项

从java.lang.Record继承的所有成员。除非显式在记录主体中重写,R隐式声明了重写中的equals、hashCode和toString方法java.lang.Record.

是否应该显式地使用java.lang.Record中的任何一个方法在记录主体中声明,实现应满足java.lang.Record.中指定的预期语义

特别是,自定义equals实现必须满足记录副本必须等于该记录的预期语义。

是否需要的答案实际上是-这取决于您决定创建为Record的实体的实现。编译或运行时也没有任何限制来约束您这样做,无论如何,扩展Object的类总是如此。

头部

另一方面,该提案的主要动机之一是"低值、重复、易出错的代码:构造函数、访问器、equals()hashCode()toString()"。在数据载体中,这在当今的Java编程中非常常见。因此,如前所述,决定更倾向于语义目标

…:将数据建模为数据(如果语义是正确的,样板会自行处理。)它应该简单、清晰、简洁地声明不可变,表现良好的标称数据聚合。

尾部

因此,样板已经处理好了,但请注意,出于某种原因,您可能仍然希望您的一个记录组件不被视为两个不同对象之间比较过程的一部分,这就是您可能希望覆盖所提供的equalshashCode的默认实现的地方。此外,毫无疑问,在我的想法中,toString有时会有一些幻想,因此也需要覆盖

以上大部分不能归类为编译或运行时失败,但提案本身也包含了随之而来的风险:

从状态自动派生的任何成员描述也可以显式声明。然而,不小心实现accessors或equals/hashCode有破坏记录的语义不变量。

什么是Java记录关于Java最常见的抱怨之一是,您需要为一个类编写大量代码有用的通常你需要写以下内容:

  1. toString()
  2. hashCode()
  3. equals()
  4. Getter方法
  5. 公共构造函数

对于简单的域类,这些方法通常很无聊,重复的,以及可以很容易生成的东西机械地(并且IDE通常提供这种能力),语言本身并没有提供任何实现这一点的方法。

记录的目标是扩展Java语言语法,并创建说一个类是"字段,只有字段,什么都没有"但是田野。"通过对一个类进行陈述编译器可以通过自动创建所有方法并具有所有字段都参与了hashCode()等方法。

对于记录内的所有属性,记录附带了hashCode()equals()toString()默认实现

hashCode()的默认实现

记录将使用记录内所有属性的哈希代码

默认实现等于()

记录将使用所有属性来决定两个记录是否等于

因此,任何哈希实现,例如HashSet、LinkedHashSet、HashMap、LinkedHashMap、

等等将使用CCD_ 18,并且在任何碰撞的情况下将使用CCD_

默认实现还是自定义实现

如果要使用hashCode()equals()中的所有属性,则不要覆盖

是否需要为记录重写hashCode()和equals()

这取决于你是否保留默认的实现,或者只为选择一些属性

任何内容,但如果您想要自定义属性,则可以覆盖以决定属性决定相等性,属性使hashCode成为

在默认实现中如何计算hashCode

将使用整数和字符串的hashCode,如下所示:

int hashCode = 1 * 31;
hashCode = (hashCode + "a".hashCode()) & 0x7fffffff;

,下面的代码带有hashCode()equals()的默认实现

以及CCD_ 24。

HashSet没有添加它们中的两个,因为这两个记录具有相同的hashCode并且等于

static record Record(int id, String name) {
}
public static void main(String[] args) {
Record r1 = new Record(1, "a");
Record r2 = new Record(1, "a");
Set<Record> set = new HashSet<>();
set.add(r1);
set.add(r2);
System.out.println(set);
System.out.println("Hashcode for record1: " + r1.hashCode());
System.out.println("Hashcode for record2: " + r2.hashCode());
int hashCode = 1 * 31;
hashCode = (hashCode + "a".hashCode()) & 0x7fffffff;
System.out.println("The hashCode: " + hashCode);
}

,输出

[Record[id=1, name=a]]
Hashcode for record1: 128
Hashcode for record2: 128
The hashCode: 128

,资源:

博客oracle

最新更新