将类转换为记录时的兼容性问题 [英] Compatibility issues while converting Classes to Records

查看:89
本文介绍了将类转换为记录时的兼容性问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在与以下名为 City 的类一起工作

I have been working with the following class named City

@ToString
@AllArgsConstructor
public class City {
    Integer id;
    String name;
}

并尝试将其转换为记录称为 CityRecord as

and tried to convert it to a record called CityRecord as

record CityRecord(Integer id, String name) {} // much cleaner!

但是转向这样的表示形式,我们的单元测试之一开始失败。这些测试在内部处理从JSON文件读取并映射到对象的城市列表,从而进一步对城市进行计数,同时将其分组为 Map 。简化为以下内容:

But moving to such a representation, one of our unit tests starts failing. The tests internally deal with a list of cities read from a JSON file and mapped to an object further counting the cities while grouping them under into a Map. Simplified to something like:

List<City> cities = List.of(
        new City(1, "one"),
        new City(2, "two"),
        new City(3, "three"),
        new City(2, "two"));
Map<City, Long> cityListMap = cities.stream()
        .collect(Collectors.groupingBy(Function.identity(),
                Collectors.counting()));

上面的代码断言true包含4个键,每个键占其出现的1个。使用记录表示法,在生成的 Map 中最多可以有3个键。是什么原因造成的,应该怎么解决?

The above code asserted true to contain 4 keys and each accounting for 1 of its occurrence. With the record representation, there are no more than 3 keys in the resulting Map. What is causing this and what should be the way to go around this?

推荐答案

原因


观察到的行为背后的原因如 java.lang.Record


对于所有记录类,必须保持以下不变式:如果记录
R的成分是c1,c2,... cn,则如果按如下方式复制记录实例

For all record classes, the following invariant must hold: if a record R's components are c1, c2, ... cn, then if a record instance is copied as follows:

 R copy = new R(r.c1(), r.c2(), ..., r.cn());   then it must be the case that r.equals(copy).


简而言之,您的 CityRecord 类现在具有 equals (和哈希码)实现,该实现将两个属性进行比较,并确保它们是否相等,包含这些成分的记录也相等。评估的结果是,将具有相同属性的两个记录对象分组在一起。

In short, your CityRecord class now has an equals(and hashcode) implementation that compares the two attributes and ensure if they are equal the record consisting of those components are also equal. As a result of this evaluation, the two record objects with the same attributes would be grouped together.

因此,推断/断言应该有三个这样的键的结果是正确的而其中一个,名称=两个 被计算两次。

The result, therefore, would be correct to infer/assert that there should be three such keys with the one having id=2, name="two" counted twice.

对此的一种立即解决方案是在您的记录表示中创建一个自定义(有瑕疵的原因,稍后说明)等于的实现。看起来像这样:

An immediate temporary solution to this would be to create a custom(flawed - reason explained later) equals implementation within your record representation as well. This would look like:

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 类,您的测试就可以正常进行。但是,在使用任何此类补救措施之前,您必须注意以下警告。

Now that the comparison would be between two objects as in while using the existing City class, your tests would just work fine. But you must note the caution below before using any such remedy.

作为 JEP-359 读取,记录更像是数据载体,并且在选择迁移现有的类时,您必须了解记录自动获取的标准成员

As the JEP-359 reads, Records are more like "data carrier" and while choosing to migrate your existing classes, you must be aware of the standard members acquired by a record automatically.

计划迁移一个类必须了解当前实现的完整详细信息,例如在您按 City 分组时引用的示例中,没有理由让两个城市的<$ c $相同c> id 和 name data 的列出方式有所不同。它们应该相等,应该是所有重复的两次之后的相同数据,因此应该是正确的计数。

Planning to migrate one must be aware of the complete details of the current implementation, such as in the example you quoted while you've grouped by City, there should be no reason to have two cities with same id and name data to be listed differently. They should be equal, it should be the same data after all repeated twice and hence the correct counts.

在这种情况下,您现有的实现(如果表示一个数据模型)可以通过覆盖等于实现,以纠正与记录匹配的方式。还要考虑比较各个属性,因此上述立即采取的补救措施是矛盾的,应该避免。

In which case, your existing implementation if representing a data model could be rectified to match the record in a way by overwriting the equals implementation to account for comparing the individual attributes as well which is where the immediate remedy stated above is contradictory and should be avoided.

这篇关于将类转换为记录时的兼容性问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆