解析JSON文件时如何让两个不同的ArrayList引用同一个对象
实现方案
核心逻辑为在解析过程中加入实例缓存机制,通过唯一身份标识复用已创建的Person对象,避免重复实例化。
步骤1:定义Person类的相等规则
首先给Person类重写equals()和hashCode()方法,默认可以用姓名组合作为唯一判断依据,若业务存在学号、工号等唯一ID,优先使用唯一ID判断准确性更高。
import java.util.Objects; public class Person { private String firstname; private String lastname; // 构造方法、Getter、Setter自行补充 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return Objects.equals(firstname, person.firstname) && Objects.equals(lastname, person.lastname); } @Override public int hashCode() { return Objects.hash(firstname, lastname); } }
步骤2:解析时新增缓存复用逻辑
解析JSON时先创建全局缓存容器,每解析到一个Person节点先查询缓存:存在对应实例则直接复用,不存在则新建并存入缓存,最后将实例添加到对应的TA/Student列表即可。以下是Jackson解析库的示例代码,其他JSON库逻辑完全一致,仅节点读取API不同:
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; // 初始化缓存和列表 Map<Person, Person> personCache = new HashMap<>(); List<Person> taList = new ArrayList<>(); List<Person> studentList = new ArrayList<>(); ObjectMapper objectMapper = new ObjectMapper(); // 读取JSON根节点 JsonNode root = objectMapper.readTree(yourJsonStr); // 解析TA列表 JsonNode taNodes = root.get("TA"); for (JsonNode node : taNodes) { Person temp = objectMapper.treeToValue(node, Person.class); // 缓存中无对应实例则存入,有则直接返回已有实例 Person realPerson = personCache.computeIfAbsent(temp, k -> temp); taList.add(realPerson); } // 解析Student列表 JsonNode studentNodes = root.get("Student"); for (JsonNode node : studentNodes) { Person temp = objectMapper.treeToValue(node, Person.class); Person realPerson = personCache.computeIfAbsent(temp, k -> temp); studentList.add(realPerson); }
- 处理完成后,两个列表中的John Smith会指向同一个Person实例,修改该实例的属性会在两个列表中同步生效。
- 若业务存在重名场景,必须新增唯一ID字段作为equals和hashCode的判断依据,避免错误复用不同人的实例。
内容的提问来源于stack exchange,提问作者Will
相关产品推荐
相关产品推荐

