前言

现在大部分都是后端封装树形结构,第一次做的时候想从网上找通用,发现大部分都是要用类的get/set方法,不一样就要改,毕竟懒,改就改改,后来发现部门要,地区要,分类要,于是想着就把之前的用注解和反射做成通用的,当时改的下面这种的

改完之后在我的电脑上测试发现处理456条数据要3000毫秒左右(测试结果不同的电脑不一样)

终于在今天凌晨4点的时候灵光一闪,把所有的数据遍历不到两遍就可以,

思路

代码

注解类:

import java.lang.annotation.ElementType;

import java.lang.annotation.Retention;

import java.lang.annotation.RetentionPolicy;

import java.lang.annotation.Target;

/**

* @author ***

* @version 1.0

* @date 2020/7/28 16:12

* 树形封装注解

* value:id 主键id

* pid 父级别id

* list 子列表

* level:等级,由高到底,逗号分割

*/

@Retention(RetentionPolicy.RUNTIME)

@Target(value = {ElementType.FIELD})

public @interface TreeType {

//注解成员,default表示默认值

public String value() default "";

public String level() default "";

}

tree工具类

package com.mooc1993.common.utils;

import com.mooc1993.common.annotate.TreeType;

import org.springframework.util.StringUtils;

import java.beans.IntrospectionException;

import java.beans.PropertyDescriptor;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.util.*;

import java.lang.reflect.Field;

/**

* @author ***

* @version 1.0

* @date 2020/7/28 15:47

*/

public class TreeObjectUtils {

//主键id字段名

private String id;

//父级id字段名

private String parentId;

//子级集合字段名

private String child;

//等级集合,从高到底。如:1,2,3

private List level;

//等级字段名

private String levelName;

//key父id

//value索引

private Map map = null;

/**

* 获取树形结构

* @param list

* @param

* @param

* @return

*/

public List get1(List list) {

if (null == list) {

return list;

}

int size = list.size();

if (size == 0) {

return list;

}

getType(list.get(0));

map = new HashMap<>(list.size());

int levelSize = level.size();

Map> levelMap = new HashMap<>(levelSize);

for (int i = 0; i < size; i++) {

T t = list.get(i);

Object key = getName(id, t, null);

Object mapLevel = getName(levelName, t, null);

List levelLists = levelMap.get(mapLevel);

Integer index = null;

if (null == levelLists) {

List levelList = new ArrayList<>();

index = 0;

levelList.add(t);

levelMap.put(mapLevel, levelList);

} else {

index = levelLists.size();

levelLists.add(t);

levelMap.put(mapLevel, levelLists);

}

map.put(key, index);

}

for (int i = levelSize - 1; i > 0; i--) {

List levelLists = levelMap.get(level.get(i));

int size1 = levelLists.size();

for (int j = 0; j < size1; j++) {

T unit = levelLists.get(j);

//获取父级id

Object key = getName(parentId, unit, null);

//获取索引id

Integer integer = map.get(key);

//获取上一级对象

List tList = levelMap.get(level.get(i - 1));

T t = tList.get(integer);

List childList = (List) getName(child, t, null);

if (null == childList) {

childList = new ArrayList<>();

}

childList.add(unit);

getName(child, t, childList);

}

}

return levelMap.get(level.get(0));

}

/**

* 通过反射获取注解对应的字段名

*

* @param t

*/

public void getType(T t) {

// 反射获得 class

Class> clazz = t.getClass();

// 如果类 上有注解 @TreeType ,取出注解 value的值

TreeType declaredAnnotation = clazz.getDeclaredAnnotation(TreeType.class);

if (declaredAnnotation != null) {

System.out.println("类的注解@TreeType的value值是:" + declaredAnnotation.value());

}

//获得所有该类方法,不包括从其他地方继承过来的

Field[] declaredFields = clazz.getDeclaredFields();

for (Field declaredField : declaredFields) {

TreeType fieldAnnotation = declaredField.getDeclaredAnnotation(TreeType.class);

if (fieldAnnotation != null) {

String value = fieldAnnotation.value();

String level = fieldAnnotation.level();

String name = declaredField.getName();

//首字母转大写,拼接get,set方法。反射调用不拼接,不使用

//name=toUpperCaseFirstOne(name);

if ("id".equals(value)) {

Home | This.ID = name;

} else if ("pid".equals(value)) {

this.parentId = name;

} else if ("list".equals(value)) {

this.child = name;

} else if (!StringUtils.isEmpty(level)) {

this.level = Arrays.asList(level.split(","));

this.levelName = name;

}

}

}

}

/**

* 通过反射调用方法获取参数

*

* @param name 方法名

* @param obj 类

* @param arg 参数

* @return

*/

private Object getName(String name, Object obj, Object arg) {

PropertyDescriptor pd = null;

try {

pd = new PropertyDescriptor(name, obj.getClass());

} catch (IntrospectionException e) {

e.printStackTrace();

}

//获取set方法

Method getMethod = pd.getReadMethod();

//获取get方法

Method getMethod1 = pd.getWriteMethod();

Object rtn = null;

try {

if (arg == null) {

rtn = getMethod.invoke(obj);

} else {

getMethod1.invoke(obj, arg);

}

} catch (IllegalAccessException e) {

e.printStackTrace();

} catch (InvocationTargetException e) {

e.printStackTrace();

}

return rtn;

}

}

例子:

@Data

public class FcSkillsType implements Serializable {

@TreeType("id")

private Integer typeId;

private String typeName;

@TreeType(level = "1,2,3,4,5")

private String typeLevel;

@TreeType("pid")

private Integer typeFatherId;

private String skillYpeIcon;

private Boolean isDelete;

@TreeType("list")

private List typeList;

}

测试

用这种思路加反射和注解测试处理456条数据大概要30毫秒左右,如果不使用注解和反射,直接类.属性大概率1毫秒。

不足

工具还有好多不足和需要优化的地方,

比如等级要提前写入,不能根据数据自动扩展,这里我稍微处理了一下,假如预计会分3个等级(1,2,3),你可以在注解上多写几个,比如1,2,3,4,5,他不会影响代码的运行

还有对反射获取到的参数没有校验

注意反射获得所有该类方法,不包括从其他地方继承过来的

等等…

java 树结构_Java通用tree树形结构相关推荐

  1. 使用ztree.js,受益一生,十分钟学会使用tree树形结构插件

    看到ztree.js,这几个字眼,毋庸置疑,那肯定就是tree树形结构了,曾经的swing年代有jtree,后来jquery年代有jstree和treeview,虽然我没写过,但是我见过,一些小功能做 ...

  2. java arraylist 遍历树_Java递归遍历树形结构

    废话不多说了,直接给大家贴代码,具体代码如下所示://菜单树形结构 public JSONArray treeMenuList(JSONArray menuList, int parentId) { ...

  3. 把数据转换为在内存中Tree(树形结构)。_备战秋招:一文搞定数据库常见面试题...

    点击上方"蓝字",关注了解更多 1.数据库范式 第一范式:列不可分,eg:[联系人](姓名,性别,电话),一个联系人有家庭电话和公司电话,那么这种表结构设计就没有达到 1NF: 第 ...

  4. java swing 树_JavaSwing实现树形结构 | 学步园

    一.Applet package com.jy.applet.day1206; import java.awt.Container; import javax.swing.JApplet; impor ...

  5. 关于element tree树形结构设置默认展开第一级,第二级,第三级,以此类推

    官方default-expand-all是否默认展开所有节点,这个在这里已经不够用了. 第一步:设置node-key属性,每个树节点用来作为唯一标识的属性,整棵树应该是唯一的.例如:node-key= ...

  6. XML Tree(树形结构)

    xml文档(xml document)使用树形结构表达,以根结点root为开始,逐渐向下发散.它使用一种可自我描述的简单的语法. 一个xml文档分为文件序言(declaration)和文件主体两个大的 ...

  7. EasyUI之Tree树形结构(一)

    官网地址:www.jeasyui.net/plugins/186- 前端代码: $("#menuTreegrid").treegrid({url: SysResource.URL. ...

  8. java实现处理无限层级树形结构

    树形结构在实际业务中是很经常遇到的,比如说机构.菜单.部门等等业务就会经常遇到层级关系.一般层级处理,有两种方式 (1)将所有的数据返回给前端,由前端处理,组装成树形结构,别担心,前端有组件的,只要后 ...

  9. 03【若依框架解读】Tree树形结构的控制(菜单,部门)

    背景 若依管理框架中包含了不少菜单树和权限树的控制,主要实现的方式是递归,比较容易阅读和理解.构建属性结构本身是开发中非常常见的场景.掌握后非常容易在工作中使用. 属性结构控制 后端返回列表,前端控制 ...

最新文章

  1. C++_STL——array(C++11)
  2. vlfeat 特征检测
  3. 禁止复制的网页怎么复制
  4. PHP获取文件后缀名
  5. tcp协议中的长连接和短连接服务器,谈谈HTTP协议中的短轮询、长轮询、长连接和短链接...
  6. 【数据库系统】为什么使用SQL而非C/C++的函数库执行数据库查询操作
  7. html动态生成按钮事件无效,【iCheck】通过 JS 动态生成的元素点击无效的解决方法...
  8. 2020款iPhone SE最快下周发布:价格3000以内
  9. caged系统pdf_热电材料的应用和研究进展.pdf
  10. Linux内核之capabilities能力
  11. (NCRE网络技术)IP地址规划设计技术-知识点
  12. 读懂用户运营体系:用户分层和分群
  13. 第三阶段应用层——1.11 数码相册—setting_page设置页面的显存管理、页面规划、输入控制
  14. 计算机主机配置科普,电脑装机配置 篇八:电脑内存如何选购?内存科普--小白篇...
  15. 工作日,我们又团建了!
  16. 04 带宽管理的队列规定
  17. 教授专栏12|龚亚平:走出危机困局,取决员工创造力
  18. android 系统的切图方式_android APPUI设计、切图的常用尺寸大全
  19. 毕业设计 单片机智能灌溉系统 - 物联网 嵌入式
  20. 使用kettle采集excel表格中的数据

热门文章

  1. 【UVM基础】CallBack机制快速上手指南
  2. 强化练习200题(二)正题:123
  3. adobe air for ubuntu + markman 安装?
  4. html模态框插件,如何使用JavaScript构建模态框插件
  5. MI5s安装LineageOS 16
  6. rhce8的rh294练习环境
  7. WIN7下默认网关丢失该如何解决
  8. IP地址库介绍 (转)
  9. 交易心得(简要总结)
  10. ubuntu服务器登桌面,Ubuntu Server安装桌面环境实现图形化访问 | 聂扬帆博客