如何返回树状数据结构?
一、如何创建树状数据结构?
1、创建数据库表 City
DROP TABLE IF EXISTS `city`;CREATE TABLE `city` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT "主键",
`name` varchar(255) DEFAULT NULL COMMENT "城市名",
`name_en` varchar(255) DEFAULT NULL COMMENT "城市英文名",
`parent_id` int(11) DEFAULT NULL COMMENT "父节点ID",
`del` int(1) NOT NULL DEFAULT "0" COMMENT "假删除 0-未删除 1-已删除",
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
INSERT INTO `city` VALUES ("1", "江西省", "JiangXi", "0", "0");
INSERT INTO `city` VALUES ("2", "赣州市", "GanZhou", "1", "0");
INSERT INTO `city` VALUES ("3", "信丰县", "XinFeng", "2", "0");
INSERT INTO `city` VALUES ("4", "南昌市", "NanChang", "1", "0");
INSERT INTO `city` VALUES ("5", "兴国县", "XinGuo", "2", "0");
2、创建相应的实体类 City
@Entity@Table(name = "city")
@Data
public class City implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
private String nameEn;
private Integer parentId;
@Column(insertable = false)
private Integer del;
}
3、创建相应的 CityRepository
- 其中继承 JpaSpecificationExecutor<City> 是为了添加查询筛选条件
public interface CityRepository extends JpaRepository<City, Integer>, JpaSpecificationExecutor<City> {}
4、创建相应的 CityService
public interface CityService { /**
* 返回树状结构数据
* @return
*/
List<CityTree> buildTree();
}
- 其中用到的
CityTree
展示类
@Data@EqualsAndHashCode
public class CityTree extends TreeNode {
private String name;
private String nameEn;
public CityTree(){
}
}
- 继承所用到的
TreeNode
类
@Datapublic class TreeNode implements Serializable {
private static final long serialVersionUID = 8772115911922451037L;
protected Object id;
protected Object parentId;
protected List<TreeNode> children = new ArrayList<TreeNode>();
public void add(TreeNode node) {
children.add(node);
}
}
5、创建相应的 CityServiceImpl 实现类
@Servicepublic class CityServiceImpl implements CityService {
@Autowired
private CityRepository cityRepository;
@Override
public List<CityTree> buildTree() {
//添加筛选条件
Specification<City> specification = (Specification<City>) (root, criteriaQuery, criteriaBuilder) -> {
List<Predicate> predicates = new ArrayList<>();
predicates.add(criteriaBuilder.equal(root.get("del").as(Integer.class), 0));
Predicate[] pre = new Predicate[predicates.size()];
return criteriaQuery.where(predicates.toArray(pre)).getRestriction();
};
List<City> cityList = cityRepository.findAll(specification);
// cityList 为查询到的结果集, 0 代表的是根节点
return CityTreeUtil.buildCityTree(cityList, 0);
}
}
- 其中用到的
CityTreeUtil
工具类
@UtilityClasspublic class CityTreeUtil {
/**
* @param cityList
* @param root
* @return
*/
public List<CityTree> buildCityTree(List<City> cityList, int root) {
List<CityTree> trees = new ArrayList<>();
CityTree node;
for (City city : cityList) {
node = new CityTree();
BeanUtils.copyProperties(city, node);
node.setId(city.getId());
node.setParentId(city.getParentId());
trees.add(node);
}
return TreeUtil.buildByLoop(trees, root);
}
}
- 其中用到的
TreeUtil
工具类
@UtilityClasspublic class TreeUtil {
/**
* 两层循环实现建树
* @param treeNodes 传入的树节点列表
* @return
*/
public <T extends TreeNode> List<T> buildByLoop(List<T> treeNodes, Object root) {
List<T> trees = new ArrayList<>();
for (T treeNode : treeNodes) {
if (root.equals(treeNode.getParentId())) {
trees.add(treeNode);
}
for (T it : treeNodes) {
if (it.getParentId().equals(treeNode.getId())) {
if (treeNode.getChildren() == null) {
treeNode.setChildren(new ArrayList<>());
}
treeNode.add(it);
}
}
}
return trees;
}
/**
* 使用递归方法建树
* @param treeNodes
* @return
*/
public <T extends TreeNode> List<T> buildByRecursive(List<T> treeNodes, Object root) {
List<T> trees = new ArrayList<T>();
for (T treeNode : treeNodes) {
if (root.equals(treeNode.getParentId())) {
trees.add(findChildren(treeNode, treeNodes));
}
}
return trees;
}
/**
* 递归查找子节点
*
* @param treeNodes
* @return
*/
public <T extends TreeNode> T findChildren(T treeNode, List<T> treeNodes) {
for (T it : treeNodes) {
if (it.getParentId().equals(treeNode.getId())) {
if (treeNode.getChildren() == null) {
treeNode.setChildren(new ArrayList<>());
}
treeNode.add(findChildren(it, treeNodes));
}
}
return treeNode;
}
/**
* 查找TreeNode集合中 所有没有子节点的元素的id
* @param roleTree
* @return
*/
public Set<Object> filterChild(List<TreeNode> roleTree) {
Set<Object> grantMenu = new TreeSet<>();
roleTree.forEach(treeNode -> {
grantMenu.addAll(recursion(treeNode, grantMenu));
});
return grantMenu;
}
public Set<Object> recursion(TreeNode root, Set<Object> result) {
List<TreeNode> treeNodes = root.getChildren();
// TODO 没有子节点的直接加入数组
if (treeNodes == null || treeNodes.size() <= 0) {
result.add(root.getId());
//如果该节点没有子节点,将其加入解集,并结束递归
return result;
}
// TODO 有子节点则遍历后在查找
for (TreeNode treeNode : treeNodes) {
recursion(treeNode, result);
}
//否则的话,对其每一个子节点执行递归函数
return result;
}
}
6、创建相应的 Controller
@RestController@RequestMapping("/city")
public class CityController {
@Autowired
private CityService cityService;
@GetMapping("/tree")
public Result buildTree(){
List<CityTree> cityTrees = cityService.buildTree();
return Result.success(cityTrees);
}
}
7、结果
{ "code": 200,
"msg": "success",
"data": [
{
"id": 1,
"parentId": 0,
"children": [
{
"id": 2,
"parentId": 1,
"children": [
{
"id": 3,
"parentId": 2,
"children": [],
"name": "信丰县",
"nameEn": "XinFeng"
},
{
"id": 5,
"parentId": 2,
"children": [],
"name": "兴国县",
"nameEn": "XinGuo"
}
],
"name": "赣州市",
"nameEn": "GanZhou"
},
{
"id": 4,
"parentId": 1,
"children": [],
"name": "南昌市",
"nameEn": "NanChang"
}
],
"name": "江西省",
"nameEn": "JiangXi"
}
]
}
以上是 如何返回树状数据结构? 的全部内容, 来源链接: utcz.com/z/511970.html