如何返回树状数据结构?

编程

一、如何创建树状数据结构

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

@Data

public 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 实现类

@Service

public 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 工具类

@UtilityClass

public 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 工具类

@UtilityClass

public 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

回到顶部