List工具类
list和树互转
TreeNodeUtil
泛型基类
java
import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
/**
* 树节点结构 的基类。 要想用 TreeNodeUtil 工具类 必须继承这个类才可以进行转换
*/
@Data
public class TreeNode<K,T> implements Serializable {
/** 主键 */
private K id;
/** 父菜单ID */
private K parentId;
/** 导航名字 */
private String name;
/** 排序 */
private Integer sort;
/** 层级 */
private Integer deep;
/** 下级节点 */
List<T> childList = new ArrayList<>();
}
工具类
java
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;
/**
* 树工具类
* 公众号:干货食堂
*/
public class TreeNodeUtil {
/**
* list 转 tree
* @param list
* @param parentId
* @param deep 树深度
* @return
*/
public static <K, T extends TreeNode<K, T>> List<T> convertTreeNode(List<T> list, K parentId, Integer deep){
//子类
List<T> children = list.stream().filter(x -> x.getParentId().equals(parentId)).collect(Collectors.toList());
children.forEach(e -> e.setDeep(deep));
//排序,即便是sql不排序 也可以用代码实现
children = children.stream().sorted(Comparator.comparing(T::getSort)).collect(Collectors.toList());
//后辈中的非子类
List<T> successor = list.stream().filter(x -> !x.getParentId().equals(parentId)).collect(Collectors.toList());
children.forEach(x ->
{
convertTreeNode(successor, (K)x.getId(),deep + 1).forEach(
y -> x.getChildList().add(y)
);
}
);
return children;
}
public static <T extends TreeNode> List<T> convertTreeNode(List<T> dataList) {
//key 级别,值 数据列表
Map<Integer, List<T>> levelMap = dataList.stream().
collect(Collectors.groupingBy(e -> e.getDeep(), TreeMap::new, Collectors.toList()));
//所有级别
List<Integer> levelList = levelMap.keySet().stream().sorted().collect(Collectors.toList());
for (Integer level : levelList) {
//获取当前级别的数据列表
List<T> tableDataList = levelMap.get(level);
int childLevel = level + 1;
List<T> childTableDataList = levelMap.get(childLevel);
if (childTableDataList == null || childTableDataList.size() == 0) break;
for (T tableData : tableDataList) {
List<T> childList = childTableDataList.parallelStream()
.filter(child -> child.getParentId().equals(tableData.getId()))
.sorted(Comparator.comparing(e -> e.getSort()))
.collect(Collectors.toList());
tableData.setChildList(childList);
}
}
return levelMap.get(1).stream().sorted(Comparator.comparing(e -> e.getSort())).collect(Collectors.toList());
}
/**
* tree 转 list
* @param list
* @param target
*/
public static <T extends TreeNode> void treeToList(List<T> list, List<T> target){
for (int i = 0; i < list.size(); i++) {
T my_menuNode = list.get(i);
List<T> children = my_menuNode.getChildList();
children = children.stream().sorted(Comparator.comparing(T::getSort)).collect(Collectors.toList());
if (children.size()>0){
treeToList(children,target);
}
target.add(my_menuNode);
}
}
}
TreeNodeUtil2
java
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 树工具类
* 公众号:干货食堂
*/
public class TreeNodeUtil2{
/**
* 递归向上查找法
*/
public static <K, T extends TreeNode<K, T>> List<T> convertTreeNode(List<T> nodeList) {
Map<K, T> nodeMap = new LinkedHashMap<>(16);
for (T node : nodeList) {
nodeMap.put(node.getId(), node);
}
return buildTree(nodeMap);
}
/**
* 递归向上查找父节点
*/
public static <K, T extends TreeNode<K, T>> List<T> buildTree(Map<K, T> nodeMap) {
return findParent(nodeMap);
}
/**
* 利用HashMap高效率递归向上查找,并每次减少遍历节点数
*/
public static <K, T extends TreeNode<K, T>> List<T> findParent(Map<K, T> nodeMap) {
//该循环结束后可以移除掉的节点
List<K> removeNodes = new ArrayList<>();
for (T node : nodeMap.values()) {
T pNode = nodeMap.get(node.getParentId());
//如果当前节点的父节点存在,则将当前节点添加到父节点的子节点,并在循环结束后从Map中删除当前节点
if (pNode != null) {
pNode.getChildList().add(node);
removeNodes.add(node.getId());
}
}
//删除已经找到父节点的节点
removeNodes.forEach(nodeMap::remove);
List<T> treeList = new ArrayList<>(nodeMap.values());
return sortTree(treeList);
}
/**
* 遍历并排序树结构
* @param treeList 树结构列表
* @return 排序后的树结构列表
*/
public static <K, T extends TreeNode<K, T>> List<T> sortTree(List<T> treeList) {
// 对树的根节点进行排序
treeList = treeList.stream()
.sorted(Comparator.comparing(T::getSort))
.collect(Collectors.toList());
Integer deep = 1;
// 遍历每个节点,并递归排序其子节点
treeList.forEach(e -> {
e.setDeep(deep);
sortChildren(e,deep);
});
return treeList;
}
/**
* 递归排序节点的子节点
* @param node 当前节点
*/
private static <K, T extends TreeNode<K, T>> void sortChildren(T node,Integer deep) {
List<T> children = node.getChildList();
if (children != null && !children.isEmpty()) {
// 对子节点进行排序
children = children.stream()
.sorted(Comparator.comparing(T::getSort))
.collect(Collectors.toList());
// 更新当前节点的子节点列表
node.setChildList(children);
// 递归排序每个子节点的子节点
deep+=1;
Integer finalDeep = deep;
children.forEach(e -> {
e.setDeep(finalDeep);
sortChildren(e, finalDeep);
});
}
}
}
Map结构
map比较特殊,专门写一个
java
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 树工具类
*/
public class TreeNodeUtil3 {
/**
* 递归向上查找法
*/
public static List<Map<String,Object>> convertTreeNode(List<Map<String,Object>> nodeList) {
Map<String,Map<String,Object>> nodeMap = new LinkedHashMap<>(16);
for (Map<String,Object> node : nodeList) {
nodeMap.put(node.get("id").toString(), node);
}
return buildTree(nodeMap);
}
/**
* 递归向上查找父节点
*/
private static List<Map<String,Object>> buildTree(Map<String,Map<String,Object>> nodeMap) {
return findParent(nodeMap);
}
/**
* 利用HashMap高效率递归向上查找,并每次减少遍历节点数
*/
private static List<Map<String,Object>> findParent(Map<String,Map<String,Object>> nodeMap) {
//该循环结束后可以移除掉的节点
List<String> removeNodes = new ArrayList<>();
for (Map<String,Object> node : nodeMap.values()) {
Map<String,Object> pNode = nodeMap.get(node.get("pId").toString());
//如果当前节点的父节点存在,则将当前节点添加到父节点的子节点,并在循环结束后从Map中删除当前节点
if (pNode != null) {
((ArrayList)pNode.get("child")).add(node);
removeNodes.add(node.get("id").toString());
}
}
//删除已经找到父节点的节点
removeNodes.forEach(nodeMap::remove);
List<Map<String,Object>> treeList = new ArrayList<>(nodeMap.values());
return sortTree(treeList);
}
/**
* 遍历并排序树结构
* @param treeList 树结构列表
* @return 排序后的树结构列表
*/
private static List<Map<String,Object>> sortTree(List<Map<String,Object>> treeList) {
// 对树的根节点进行排序
treeList = treeList.stream()
.sorted(Comparator.comparing(m -> (Integer)m.get("sort")))
.collect(Collectors.toList());
Integer deep = 1;
// 遍历每个节点,并递归排序其子节点
treeList.forEach(e -> {
e.put("deep",deep);
sortChildren(e,deep);
});
return treeList;
}
/**
* 递归排序节点的子节点
* @param node 当前节点
*/
private static void sortChildren(Map<String,Object> node,Integer deep) {
List<Map<String,Object>> children = (List<Map<String,Object>>)node.get("child");
if (children != null && !children.isEmpty()) {
// 对子节点进行排序
children = children.stream()
.sorted(Comparator.comparing(m -> (Integer)m.get("sort")))
.collect(Collectors.toList());
// 更新当前节点的子节点列表
node.put("child",children);
// 递归排序每个子节点的子节点
deep+=1;
Integer finalDeep = deep;
children.forEach(e -> {
e.put("deep",finalDeep);
sortChildren(e, finalDeep);
});
}
}
}
验证
java
import org.apache.commons.lang3.StringUtils;
import org.junit.Test;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.TreeSet;
import java.util.stream.Collectors;
public class Test2 {
@Test
public void test() {
long a = System.currentTimeMillis();
List<List<String>> listData = new ArrayList<>();
listData.add(Arrays.asList("PH", "MY","SG","ID","TH","SEA"));
listData.add(Arrays.asList("Total","CN_VMI", "CN_JIT", "Local_VMI", "Local_JIT"));
listData.add(Arrays.asList("Tag1", "Tag2","Tag3"));
listData.add(getDateList("2024-01-01","2024-12-02"));
List<List<String>> list2 = getDescartes(listData);
// System.out.println(list2);
Random random = new Random();
List<Map<String,Object>> treeNodes = new ArrayList<>();
for (int i = 0; i < list2.size(); i++) {
List<String> list = list2.get(i);
for (int j = 0; j < list.size(); j++) {
String ele = list.get(j);
Map<String, Object> treeNode = new HashMap<>();
treeNode.put("id",StringUtils.join(list.subList(0, j+1),"#"));
treeNode.put("pId",j == 0 ? "#" : StringUtils.join(list.subList(0, j),"#"));
treeNode.put("name",ele);
treeNode.put("level",j+1);
treeNode.put("sort",random.nextInt(5));
treeNode.put("child",new ArrayList<>());
treeNodes.add(treeNode);
}
}
// 去重
long b = System.currentTimeMillis();
System.out.println("基础数据条数:"+treeNodes.size());
System.out.println("准备数据耗时:" + (b - a));
List<Map<String,Object>> treeNodes2 = TreeNodeUtil3.convertTreeNode(treeNodes);
long d = System.currentTimeMillis();
System.out.println("第二种方法性能耗时:" + (d - b));
}
private static <T> List<List<T>> getDescartes(List<List<T>> list) {
List<List<T>> returnList = new ArrayList<>();
descartesRecursive(list, 0, returnList, new ArrayList<>());
return returnList;
}
private static <T> void descartesRecursive(List<List<T>> originalList, int position, List<List<T>> returnList, List<T> cacheList) {
List<T> currentList = originalList.get(position); // 获取当前需要处理的子列表
for (int i = 0; i < currentList.size(); i++) {
List<T> childCacheList = new ArrayList<>(cacheList);
childCacheList.add(currentList.get(i));
// 判断是否已经处理到原始列表的最后一个子列表,如果是,则将当前组合添加到结果列表中
if (childCacheList.size() == originalList.size()) {
returnList.add(childCacheList);
} else {
// 否则继续对下一个子列表进行同样的操作
descartesRecursive(originalList, position + 1, returnList, childCacheList);
}
}
}
/**
* 获取两个日期之间的所有日期集合
*
* @param startDate
* @param endDate
* @return
*/
private static List<String> getDateList(String startDate, String endDate){
final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
List<String> listDate = new ArrayList<>();
try {
Calendar calendar = Calendar.getInstance();
calendar.setTime(dateFormat.parse(startDate));
while (calendar.getTime().before(dateFormat.parse(endDate)) || calendar.getTime().equals(dateFormat.parse(endDate))) {
listDate.add(dateFormat.format(calendar.getTime()));
calendar.add(Calendar.DAY_OF_MONTH, 1);
}
return listDate;
} catch (Exception e) {
e.printStackTrace();
}
return listDate;
}
}