递归操作本身具有一定的风险,因为层级不确定或者层级过多的话,大概率会内存溢出,所以使用的时候一定要考虑业务场景。一些传统的业务,数据量不大的话,递归还是很方便的。
下面简单写下, java 里面递归生成树形结构的实现:
本文拿行政区域做为一个示例,简单的一个查询
#实体
@Data
public class SysAreaVo {
/**
* 主键
*/ private Integer keyId;
/**
* 区域编码
*/ private String areaCode;
/**
* 区域名称
*/ private String areaName;
/**
* 区域上级编码
*/ private String parentCode;
/**
* 子集
*/ private List<SysAreaVo> children;
}
#mapper
public interface SysAreaMapper {
List<SysAreaVo> findAll();
}
#xml
<resultMap type="com.ht.cnadrc.system.client.model.vo.SysAreaVo" id="SysAreaMap">
<result property="keyId" column="key_id" jdbc Type="INTEGER"/>
<result property="areaCode" column="area_code" jdbcType="VARCHAR"/>
<result property="areaName" column="area_name" jdbcType="VARCHAR"/>
<result property="parentCode" column="parent_code" jdbcType="VARCHAR"/>
</resultMap>
<select id="findAll" resultMap="SysAreaMap">
SELECT
key_id,
area_code,
area_name,
parent_code,
FROM
sys_area
</select>
代码实现:
@SpringBootTest
@RunWith(SpringRunner.class)
public class UnitTest {
private static final String DEFAULT_NODE_ID = "0";
@Autowired
private SysAreaMapper sysAreaMapper;
@Test
public void test2() {
String nodeId = "130000";
String rootId = StringUtils.isNotBlank(nodeId) ? nodeId : DEFAULT_NODE_ID;
List<SysAreaVo> all = getAll();
List<SysAreaVo> tree = createTree(rootId, all);
System.out.println(tree);
}
private List<SysAreaVo> createTree(String pid, List<SysAreaVo> all) {
List<SysAreaVo> tree = new ArrayList<>();
for (SysAreaVo node : all) {
if (pid.equals(node.getParentCode())) {
tree.add(node);
node.setChildren(createTree(node.getAreaCode(), all));
}
}
return tree;
}
private List<SysAreaVo> getAll() {
return sysAreaMapper.findAll().stream().filter(s -> s.getAreaCode().startsWith("13")).collect(Collectors.toList());
}
}
当然有的人喜欢 Lamda的语法糖,其实没什么本质区别,下面写一个变种:
public List<SysAreaVo> createTree2(String pid, List<SysAreaVo> all) {
return all.stream().filter(s -> pid.equals(s.getParentCode()))
.peek(s -> s.setChildren(getChildNode(s, all))).collect(Collectors.toList());
}
private List<SysAreaVo> getChildNode(SysAreaVo root, List<SysAreaVo> all) {
return all.stream().filter(a -> Objects.equals(a.getParentCode(), root.getAreaCode()))
.peek(a -> a.setChildren(getChildNode(a, all))).collect(Collectors.toList());
}
@Test
public void test2() {
String rootId = "130000";
List<SysAreaVo> all = getAll();
List<SysAreaVo> tree = createTree2(rootId, all);
log.info("tree list2 = {}", tree);
}
结果示例;
下篇介绍下非递归的常规方式生成树!