多个不同对象怎么存json java_集合里的元素怎么“不见了”?

点击上方 "程序员小乐"关注, 星标或置顶一起成长

每天凌晨00点00分, 第一时间与你相约

每日英文

Sometimes there is no next time, no second chance, no time out. Sometimes it is now or never.

有时候,没有下一次,没有机会重来,没有暂停继续。有时候,错过了现在,就永远永远的没机会了。

每日掏心话

其实,痛是很难分享出去的,你复述一次你就伤一次,别人没共鸣,你就更受伤。隐忍不说,只是做事,时间会让痛过去。

来自:卡瓦邦噶!| 作者:赖信涛 | 责编:乐乐

链接:kawabangga.com/posts/3941

4eb946332bb561c87cd2cc754547cbb2.png

程序员小乐(ID:study_tech)第 802 次推文 图片来自百度

往日回顾:小米回应暴力裁员:已提前三个月通知不续签合同,并且给了N+1补偿

正文

昨天花时间在 debug 一个非常诡异的问题。Java 代码里面的一个 HashSet 集合里面命令包含这个元素,equals、hashCode 都一样,甚至对象的 id 都是一样的,但是 contains 方法返回的结果总是 false !最后花了很多时间,百思不得其解,一度怀疑我生活在 Matrix 里面。最后发现问题的一刻也恍然大悟,发现这是一个我早就知道的问题。这必定成为我职业生涯的一个污点,所以我打算记录一下这个问题。

先卖个关子吧,我来描述一下问题的背景,看你能否想到答案。

问题是这样的,我们用 JGraphT 来解决一个图的问题。这个图是我们从应用的调用关系链中生成的,生成之后会导出到 json,放到一个地方。然后所有的计算节点都可以通过这个 json 来 load 图,就不用每个节点都去清洗一遍了。一个节点清洗过后,所有的节点都从这里加载。问题主要出现图的导出和导入,图中每个节点都有一个 id,一开始我用应用的名字作为 id,导出到 json,但是导入的时候发现 Importer 会重新生成 ID,图的关系是对的,但是节点的 ID 从字符串变成了重新生成的 id 了,那么应用名字的信息就丢失了。我又给节点加上 name 属性,期望这个属性 import 之后还是好的。结果发现 import 只是 import 图的关系,并没有 import 进来其他属性(这个库看起来很 nice 啊,不知道为啥文档这么差,import 的细节都没有文档)。于是我参考 Test 里面的做法,用一个 Map 存下来节点的其他属性。然后在 import 完成之后,将这些属性 set 进去。

OK,总结一下,简单来说就是,我先从 json 导入进图,导入的时候也存下来每个节点的属性(其实就是 name),导入之后遍历图的节点,将每个属性设置进去。

问题就出现了。我用图来找最短路径的时候报错:节点不存在!

定位到库里面,判断节点不存在的 contains函数是这么写的:

3d7380451d1e6d9054ab8ea5d0f09deb.png

我 debug 了这个 Set 和 v 的关系,发现 Set 中的一个元素,跟 v 是一模一样的!对象 id 都是一样的。

equals 返回值是一样的:

0a2941bec67ff8f0ff7f089181edb7a6.png

hashCode 返回值也一样:

d61c0cd97719e7eba1e56fbb51c9964e.png

但是这个 contains 函数就是返回 false。

为了让这个问题更明显一些,我把这个问题简化成下面这段 Java 代码,可以直接运行:

import java.util.HashSet;
import java.util.Objects;
public class Vertex {
private String id;
private String name;
public Vertex(String id, String name) {
this.id = id;
this.name = name;
}
public static void main(String[] args) {
Vertex app1 = new Vertex("1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值