原因
观察到的行为背后的原因如java.lang.Record中所述
对于所有记录类,必须满足以下不变式:如果记录R的成分是c1,c2,… cn,则复制记录实例的方式如下:
R copy = new R(r.c1(), r.c2(), ..., r.cn()); then it must be the casethat r.equals(copy).
简而言之,您的
CityRecord类现在具有一个
equals(和哈希码)实现,用于比较这两个属性,并确保它们相等时,由这些组件组成的记录也相等。评估的结果是,具有相同属性的两个记录对象将被分组在一起。
因此,推断/断言应该存在三个这样的密钥而一个已经
id=2, name="two"计数了两次的结果将是正确的。
立即补救
一个直接的临时解决方案是
equals在您的记录表示形式中创建一个自定义(有缺陷的原因,稍后说明)。看起来像:
record CityRecord(Integer id, String name) { // WARNING, BROKEN CODE // Does not adhere to contract of `Record::equals` @Override public boolean equals(Object o) { return this == o; } @Override public int hashCode() { return System.identityHashCode(this); }}现在,就像使用现有
City类一样,将在两个对象之间进行比较,您的测试将正常进行。但是在使用任何此类补救措施之前,您必须注意以下注意事项。
警告
正如JEP-359所读,记录更像是“数据载体”,并且在选择迁移现有的类时,您必须意识到
记录自动获取 的 标准成员 。
计划迁移时,必须了解当前实施的完整细节,例如在按分组时引用的示例中
City,没有理由将两个城市相同
id且
name数据
列出的顺序不同。它们应该相等,所有重复 两次 后应该是 相同的数据 ,因此计数正确。 __
在这种情况下,可以
record通过覆盖
equals实现以比较各个属性的方式来纠正您现有的实现(如果表示数据模型)以与之匹配,这是上述直接补救措施相互矛盾的地方,应避免使用。



