java后台通过访问数据库得到数据来生成树是很常用的的方法
这个有很多种方法可以实现 我这里就说对我比较印象深刻的两种方法
一种是自己写的 后台拼接一点点的数据就要9秒之多
另一种是我借鉴我老大写得 后台拼接只要3面左右 (两种方法是在同样的数据和同样的环境中比较的)
为什么说这两种方法会对我影响比较大呢
因为这两种方法代表了两种实现思想
首先是我这个比较low的 我的思想就是先获取到根节点 然后通过根节点的 id 来查询所有 parentId = 根id 的数据
这样通过递归来实现 非常的慢 而且代码量非常的多
我也不怕丢人 贴出来给大家看看
/**
* 递归树 java层数据
* @param mapper
* @param parentId
* @return
*/
public static List
List
WyRoomExample example = new WyRoomExample();
WyRoomExample.Criteria ccc=example.createCriteria();
ccc.andParentIdEqualTo(parentId);
ccc.andXqIdEqualTo(xqId);
List
Comparator
@Override
public int compare(WyRoom o1, WyRoom o2) {
return o1.getCode().compareTo(o2.getCode());
}
};
Collections.sort(wyRooms,comparator);
for( WyRoom wyRoom : wyRooms ){
TreeWyRoom treeWyRoom = new TreeWyRoom();
treeWyRoom.setId(wyRoom.getId());
treeWyRoom.setParentId(wyRoom.getParentId());
treeWyRoom.setLevel(wyRoom.getLevel());
treeWyRoom.setPcId(wyRoom.getPcId());
treeWyRoom.setXqId(wyRoom.getXqId());
treeWyRoom.setCode(wyRoom.getCode());
treeWyRoom.setAlias(wyRoom.getAlias());
treeWyRoom.setType(wyRoom.getType());
treeWyRoom.setCreateDate(wyRoom.getCreateDate());
treeWyRoom.setCreator(wyRoom.getCreator());
treeWyRoom.setLastModDate(wyRoom.getLastModDate());
treeWyRoom.setLastModifier(wyRoom.getLastModifier());
treeRooms.add(treeWyRoom);
}
for(TreeWyRoom treeRoom : treeRooms){
if(treeRoom.getLevel()==2){
treeRoom.setPlzj(true);
}
treeRoom.setChildren(infiniteTree(mapper,treeRoom.getId(),xqId));
}
return treeRooms;
}
/**
* 把递归树拼接成JSON
* @param treeRoom
* @param o
* @return
*/
public static JSONArray jsonTree(List
JSONArray array = new JSONArray();
for (TreeWyRoom room : treeRoom) {
JSONObject oo = new JSONObject();
List
oo.put("id", room.getId());
oo.put("parentId", room.getParentId());
oo.put("level",room.getLevel());
oo.put("pcId",room.getPcId());
oo.put("xqId",room.getXqId());
oo.put("code",room.getCode());
oo.put("type",room.getType());
oo.put("plzj",room.getPlzj());
oo.put("alias",room.getAlias());
oo.put("creator",room.getCreator());
oo.put("createDate",room.getCreateDate());
oo.put("lastModifier",room.getLastModifier());
oo.put("lastModDate",room.getLastModDate());
if (child != null && child.size() > 0) {
oo.put("children",jsonTree(child,oo));
}
array.add(oo);
}
return array;
}
我的方法是通过两个递归来实现的 第一个递归获取到所有的数据 生成一个对象树
然后通过第二个递归来形成一个json树 最后返回jsonarray
这个方发很浅显 一点都不好 现在让我看来烂透了
除了让人可以更加明了的看到数据展示 其他一点用处都没有
在执行过程中会造成大量的数据库访问 ,对内存和缓存造成大量的浪费
这种方法的思想就是 典型的 我先获取一个点 通过这个点上的信息 来去找数据库对应的下级信息 在返回后封装children
这是个错误的示范 大家最好不要借鉴--------------------------------------------------------------------------------------------------------------------
现在让我们来看看高手 大牛 写得同样是后台Java生成的树 但是就是快
他的思想就是我先把我所有的信息都获取到 封装到一个集合中 之后再用到的时候在我的集合中获取
下面是代码 我会有重点介绍
private JSONArray getJsonArray(Integer xqId,Integer parentId){ //1.获取所有的room表 根据小区id WyRoomExample example = new WyRoomExample(); WyRoomExample.Criteria criteria = example.createCriteria(); example.setOrderByClause("id asc");//排序 criteria.andXqIdEqualTo(xqId); if(parentId != null) criteria.andParentIdEqualTo(parentId); ListwyRooms = mapper.selectByExample(example); //返回结果 JSONArray jsonArray=new JSONArray(); //region 构造树json Map ,TreeWyRoom> mapObj=new HashMap<>(); Map ,Link > mapRelation =new HashMap<>(); List rootList=new LinkedList<>(); for(WyRoom wyRoom : wyRooms){//把所有的TreeWyRoom存入mapObj中 mapObj.put(wyRoom.getId(),new TreeWyRoom(wyRoom)); Link link = new Link<>(); link.parent = wyRoom.getParentId(); //存的是 当前room的id 并把 link存进去当作child mapRelation.put(wyRoom.getId(),link); if (wyRoom.getParentId() != 0) { //如果不是顶级节点 //如果当前room的parnetId 不是0 那么就用它的parentid 来在存放关系的mapRelation中查找 并存放在link的childrens中 mapRelation.get(wyRoom.getParentId()).childrens.add(wyRoom.getId()); }else {//是楼栋 rootList.add(wyRoom.getId()); } } for(Integer roomId : rootList){ //遍历所有楼栋得到下面的子节点 JSONObject json = JSONObject.parseObject(getJsonString(roomId,mapObj,mapRelation)); jsonArray.add(json); } return jsonArray; } /**递归生成JSON树*/
private String getJsonString( int rootKey,Map,TreeWyRoom> mapObj,Map ,Link > mapRelation){ TreeWyRoom room = mapObj.get(rootKey); String s = String.format("{'id':'%d','parentId':'%d',level:'%d',pcId:'%d', xqId:'%d',code:'%s',type:'%s',plzj:'%b',alias:'%s'", room.getId(),room.getParentId(),room.getLevel(),room.getPcId(),room.getXqId(),room.getCode(),room.getType(),room.getPlzj(),room.getAlias()); if (mapRelation.get(rootKey).childrens.size()==0){ s=s +"}"; }else{ String splitDot=""; StringBuilder sb=new StringBuilder(); for(Integer childKey : mapRelation.get(rootKey).childrens ){ sb.append( splitDot).append(getJsonString(childKey, mapObj, mapRelation)); splitDot=","; } s=s + ",children:["+sb.toString()+"]}"; } return s; }
class Link<T> {//链结点 List<T> childrens=new ArrayList<T>(); // 孩子id; T parent; //父母id }
这个方法的思想就是获取所有的相关信息循环 封装成 map 方便获取
然后在通过自定义类Link 封装上下级关系 然后在存在一个公用的map中
这样 按照id的顺序就可以先把所有的父节点找出来
然后在父节点存起来 不是父节点的就在上下级关系的map中找自己的关系
最后通过递归来实现 JSONArray
============================================================
PS:我贴出来的代码是我们项目的 会有很多的不全 像是pojo这些 如果你喜欢 可以按照给出的思想 自己写写看
写过一遍后就会理解
最后感谢 网络上前辈 大牛 提供的案例和帖子 博客 谢谢 感谢老大的悉心教导