CREATE TABLE `category` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
`pid` int(12) NULL DEFAULT 0,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;
@ResponseBody
@Controller
@RequestMapping("/category")
public class CategoryController {
@Autowired
private CategoryRepository categoryRepository;
@GetMapping("/unsorted")
public Page<Category> unsorted(@RequestParam(name="page",defaultValue="0")Integer page, @RequestParam(name="size",defaultValue="15") Integer size){
//page:查询的页
//size:每页显示的数量
Pageable pageable = PageRequest.of(page,size) ;
return categoryRepository.findAll(pageable);
}
@GetMapping("hierarchy")
public List<CategoryHierarchyNode> findAll(){
List<Category> unsorted = categoryRepository.findAll();
int total = unsorted.size();
return recursivelyBuildCategoryHierarchy(unsorted.toArray(new Category[total]), total);
}
public static class CategoryHierarchyNode extends Category {
@javax.persistence.Transient
private List<CategoryHierarchyNode> subCategories;
public CategoryHierarchyNode() {
subCategories = new ArrayList<>();
}
public List<CategoryHierarchyNode> getSubCategories() {
return subCategories;
}
public void setSubCategories(List<CategoryHierarchyNode> categories) {
subCategories = categories;
}
public void addSubCategory(CategoryHierarchyNode category) {
subCategories.add(category);
}
}
private static final List<CategoryHierarchyNode> EmptyList = new ArrayList<>();
/**
* 递归整理所有Category分类
*
* @param unsorted 待整理的结点
* @param total 待整理的结点个数
* @return CategoryHierarchy分类层级关系结构
*/
private List<CategoryHierarchyNode> recursivelyBuildCategoryHierarchy(Category[] unsorted, int total) {
if (total <= 0) {
return EmptyList; // 递归终止条件1
}
// 哈希映射表, 方便搜索分类号ID
Map<Integer, Integer> map = new HashMap<>();///< key为分类号ID整数,value为数组下标i(例如unsorted[i])
for (int i = 0; i < total; i++) {
int categoryId = unsorted[i].getId();
map.put(categoryId, i);
}
// 无父母结点则为孤儿结点
List<Integer> orphanCategoryList = new ArrayList<>();///< 存储无上级分类的孤儿分类,只记录分类ID号足矣
// 有父母节点则为次级子节点
Category[] normalCategoryList = new Category[total];///< 存储分类的节点
// 遍历所有结点
int cnt = 0;
for (int i = 0; i < total; i++) {
int parentCategoryId = unsorted[i].getPid();
if (map.containsKey(parentCategoryId)) { // 检查上级结点是否存在
normalCategoryList[cnt++] = unsorted[i]; // 有上级结点则当前为普通次级结点
continue;
}
orphanCategoryList.add(unsorted[i].getId()); // 无父母则为孤儿结点
}
if (orphanCategoryList.size() <= 0 && cnt > 0) {
// 递归终止条件2, 剩余结点中可能存在循环依赖式脏数据, 可以忽略之
return EmptyList;
}
// 对剩余结点进行递归处理, 找出下一级子结点
List<CategoryHierarchyNode> children =
recursivelyBuildCategoryHierarchy(normalCategoryList, cnt);
// 创建新的List列表, 用于输出分层结果
List<CategoryHierarchyNode> hierarchy = new ArrayList<>(); // 变长数组, 以数组形式存放分类层级关系树
Map<Integer, Integer> where = new HashMap<>(); // key=CategoryID号, value=数组下标j(例如hierarchy[j])
int j = 0;
for (Integer categoryId : orphanCategoryList) {
int i = map.get(categoryId);
CategoryHierarchyNode node = new CategoryHierarchyNode();
node.setId(unsorted[i].getId());
node.setName(unsorted[i].getName());
node.setPid(unsorted[i].getPid());
hierarchy.add(node);
where.put(categoryId, j++);
}
// 遍历所有子节点, 放入树状结果并返回给上一级递归函数
for (CategoryHierarchyNode child : children) {
int parentCategoryId = child.getPid();
j = where.get(parentCategoryId);
hierarchy.get(j).addSubCategory(child);
}
return hierarchy;
}
}
网友评论