我一直在与以下名为 City
@ToString
@AllArgsConstructor
public class City {
Integer id;
String name;
}
并试图将其转换为一个record
名为CityRecord
作为
record CityRecord(Integer id, String name) {} // much cleaner!
但是转向这种表示形式,我们的单元测试之一开始失败。这些测试在内部处理从JSON文件读取并映射到对象的城市列表,进一步将城市分组到一个城市中Map
。简化为:
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。使用记录表示法,结果中的键不超过3个Map
。是什么原因造成的,解决该问题的方法应该是什么?
观察到的行为背后的原因如java.lang.Record中所述
对于所有记录类,必须满足以下不变式:如果记录R的成分是c1,c2,… cn,则复制记录实例的方式如下:
R copy = new R(r.c1(), r.c2(), ..., r.cn()); then it must be the case
that 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
实现以比较各个属性的方式来纠正您现有的实现(如果表示数据模型)以与之匹配,这是上述直接补救措施相互矛盾的地方,应避免使用。
但是当我们转向这样的表示时,我们的一个单元测试开始失败。测试在内部处理从JSON文件读取并映射到对象的城市列表,进一步计算城市数,同时将它们分组到中。简化为: 上面的代码断言为true,以包含4个键,每个键占其出现次数的1。使用记录表示法,生成的中的键不超过3个。是什么造成了这种情况?应该采取什么办法来解决这种情况?
我试图编译一个从SourceForge得到的仍在开发中的项目。这是它的地址:。https://sourceforge.net/p/groove/code/5475/tree/groove/trunk/我知道这个项目经过了很好的验证,它没有任何错误,但是当我要编译它的时候,我遇到了这个编译错误: 错误在这个文件的第370行:https://sourceforge.net/p/groove/code/
Avro SpecificRecord(即生成的java类)是否与模式演化兼容?一、 e.如果我有一个Avro消息源(在我的例子中是Kafka),并且我想将这些消息反序列化为特定的记录,那么这样做是否安全? 我所看到的: 将字段添加到架构的末尾效果很好-可以将ok反序列化为specificrecord 在中间添加字段不会破坏现有客户机 即使消息兼容,这也是一个问题。 如果我能找到新的模式(例如使用
我试图通过在一个单独的线程上进行工作并返回所需的对象来更改JavaFX中的GUI。然而,在完成工作和任务之后。setOnSucceeded()在尝试检索创建的对象时被触发,并出现错误“不兼容类型:对象无法转换为VideoScrollPane类型”。 我认为这与原始类型有关,因为这是在听众中发生的,但环顾四周后,我找不到我想要的建议。 任何可以散发的光芒都将不胜感激。
问题内容: 一般来说,对于Java和编程,我是一个新手。我正在尝试创建一个简单的程序,您可以在其中猜测我的年龄,如果您是对的,它将说“正确”,如果您错了,它将说“错”。 这是我的代码: 我收到错误消息“不兼容的类型:void无法转换为int”,但代码中没有void类?我知道我的代码可能很糟糕,但是如果你们能为我指出正确的方向,那就太好了。谢谢。 问题答案: 您的程序不必返回in 。相反,您可以将其
我试图在if语句中调用一个方法,但我总是得到以下错误。 不兼容的类型:java.lang.String不能转换为boolean