死循环代码
private List<Map<String, Object>> getJinJiangChildren(List<Map<String, Object>> list, String pcode) {
List<Map<String, Object>> result = new ArrayList();
//沿用ssx做法,和递归一个效果
for (Map<String, Object> map : list) {
if (pcode.equals(map.get("pcode"))) {
List<Map<String, Object>> cList = getJinJiangChildren(list, (String)map.get("code"));
if (CollectionUtil.isNotEmpty(cList)) {
//在头部添加
List<Map<String, Object>> tempList = new ArrayList<>();
tempList.add(map);
cList.addAll(0,tempList);
map.put("children", cList);
}
result.add(map);
}
}
return result;
}
报栈溢出。经分析,原因是(map是引用数据类型):
tempList.add(map);
cList.addAll(0,tempList); --cList里有tempList有map(引用,所有map扩大后,cList这个下标仍是指向这个扩大后的这个的map。最终导致for list的时候死循环了)
map.put("children", cList); -- map里有cList
了解到:java 复制Map对象(深拷贝与浅拷贝)HashMap的putAll()实现了深拷贝。(Map.putAll()只是浅拷贝)
private List<Map<String, Object>> getJinJiangChildren(List<Map<String, Object>> list, String pcode) {
List<Map<String, Object>> result = new ArrayList();
//沿用ssx做法,和递归一个效果
for (Map<String, Object> map : list) {
if (pcode.equals(map.get("pcode"))) {
List<Map<String, Object>> cList = getJinJiangChildren(list, (String)map.get("code"));
if (CollectionUtil.isNotEmpty(cList)) {
//在头部添加。 注意:不能直接tempList.add(map),会死循环(浅拷贝)
HashMap<String, Object> tempMap = new HashMap<>();
tempMap.putAll(map);
List<Map<String, Object>> tempList = new ArrayList<>();
tempList.add(tempMap);
cList.addAll(0,tempList);
map.put("children", cList);
System.out.println("------"+map.get("code"));
}
result.add(map);
}
}
return result;
}
-----------------Note----------------------
特殊引用类型却不会改变原值的(是因为都有final修饰嘛?), Note: 对于不可变对象(String, 基本类型的包装器, BigInteger和BigDecimal等)而言,如上例所示的deptName属性,修改前,原对象dept和拷贝对象copy虽然都是指向同一个String对象——“RD 1”,但是由于String为不可变对象,是无法修改原String的状态的,其会生成一个新的String对象——“RD 2”,并使引用变量指向其。
总结,深拷贝用法:
1.继承与重写(因为clone()是protected,包外调不到)
.clone()
implements Cloneable
//----------------------------------------
@Override
public Object clone() {
EhrWfStaffChangeEntity change = null;
try {
change = (EhrWfStaffChangeEntity) super.clone();
//如果有引用类型&&非null需要clone,再层层clone ↓
} catch (CloneNotSupportedException e) {
return null;
}
return change;
}
2.如果存在引用类型属性,且不为空,需要层层嵌套到包装为止(如此,手动转深),否则只是地址引用,公用,谁变都变;如果本身被拷贝的是null,空指针,没有指向同一地址,则无需了(无法被牵连)。
//补充默认信息当前端传null时 (但批量的操作时,ehrWfStaffChangeEntity是公用的会有问题。
//所以clone下,但又因为业务所需是/需求是是只有空值需要重新赋值(副本有指向后并不会影响母本/正本——因为母本本就没有指向)、有值的本就公用,不需要深拷贝。恰好,所以这次只要最简单的clone重写即可)
EhrWfStaffChangeEntity ehrWfStaffChangeEntity=(EhrWfStaffChangeEntity)change.clone();
addDefaultFileldsWhenNull(ehrWfStaffChangeEntity,ehrStaffEntity);
https://zhuanlan.zhihu.com/p/130413565