Skip to content

Instantly share code, notes, and snippets.

@itxve
Last active June 24, 2022 03:27
Show Gist options
  • Save itxve/a4a43a001cf54d98b3af908ae2e31bf0 to your computer and use it in GitHub Desktop.
Save itxve/a4a43a001cf54d98b3af908ae2e31bf0 to your computer and use it in GitHub Desktop.
一个从List构建到Tree的工具类

依赖项

hutool

反射这块可以自己实现

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ReflectUtil;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;
/**
* 从List->Tree构建
* @Author xueren
* @Date 2022/6/21 3:51 下午
*/
public class TreeBuilderUtilTR<T> {
@Data
@AllArgsConstructor
@ToString
public static class Node {
private Integer id;
private String label;
private Integer level;
private Integer parentId;
private List<Node> children;
}
/**
* children属性名
*/
private String childrenField = "children";
private List<T> list;
/**
* 父节点断言
*/
private Predicate<T> parentFunction;
/**
* 父节点与子节点的关联断言
* @param root 节点
* @param node 当前节点 return true :关联成功
*/
private BiPredicate<T, T> childrenLink;
/**
* 排序接口
*/
private Comparator<T> sort;
/**
* 源数组 【构造前的数组】
*
* @param list
* @return
*/
public TreeBuilderUtilTR<T> sourceList(List<T> list) {
this.list = list;
return this;
}
/**
* 构造器方法
*
* @param <T>
* @return
*/
public static <T> TreeBuilderUtilTR<T> build() {
return new TreeBuilderUtilTR<>();
}
public TreeBuilderUtilTR<T> withSort(Comparator<T> sort) {
this.sort = sort;
return this;
}
public TreeBuilderUtilTR<T> withParent(Predicate<T> parentFunction) {
this.parentFunction = parentFunction;
return this;
}
public TreeBuilderUtilTR<T> withChildrenField(String childrenField) {
this.childrenField = childrenField;
return this;
}
public TreeBuilderUtilTR<T> withChildrenLink(BiPredicate<T, T> childrenLink) {
this.childrenLink = childrenLink;
return this;
}
/**
* 将List转为树结构
*
* @return
*/
public List<T> toTree() {
Objects.requireNonNull(this.list, "list not empty");
Objects.requireNonNull(this.parentFunction, "parentFunction not empty");
Objects.requireNonNull(this.childrenLink, "childrenLink not empty");
List<T> treeList = new ArrayList<>();
//子菜单列表
List<T> chs = this.list.stream().filter(t -> !this.parentFunction.test(t)).collect(Collectors.toList());
//父菜单
this.list.stream().filter(this.parentFunction).forEach(t -> {
treeList.add(findChildren(t, chs));
});
//没构建成树返回原有的list
if (treeList.isEmpty()) {
treeList.addAll(this.list);
}
if (!Objects.isNull(this.sort)) {
Collections.sort(treeList, this.sort);
}
return treeList;
}
/**
* 查找子节点
*
* @param parent
* @param list
* @return
*/
private T findChildren(T parent, List<T> list) {
for (int i = list.size() - 1; i >= 0; i--) {
T current = list.get(i);
if (childrenLink.test(parent, current)) {
if (Objects.isNull(ReflectUtil.getFieldValue(parent, this.childrenField))) {
ReflectUtil.setFieldValue(parent, this.childrenField, new ArrayList<>());
}
//倒叙删除元素 减少下次遍历数据
list.remove(i);
//这里可以考虑处理对象而非List
List<T> topChildren = (List<T>) ReflectUtil.getFieldValue(parent, this.childrenField);
topChildren.add(findChildren(current, list));
if (!Objects.isNull(this.sort)) {
Collections.sort(topChildren, this.sort);
}
}
}
return parent;
}
/**
* 转换成另一个树对象
*
* @param fc
* @param <O>
* @return
*/
public <O> List<O> mapToObj(Function<T, O> fc) {
return this.toTree().stream().map(t -> findOutChildren(t, fc)).collect(Collectors.toList());
}
private <O> O findOutChildren(T parent, Function<T, O> fc) {
List<T> ch = (List<T>) ReflectUtil.getFieldValue(parent, this.childrenField);
if (CollectionUtil.isNotEmpty(ch)) {
ReflectUtil.setFieldValue(parent, this.childrenField, ch.stream().map(t -> findOutChildren(t, fc))
.collect(Collectors.toList()));
}
O apply = fc.apply(parent);
//设置children, map函数不需要设置children
List<O> oc = (List<O>) ReflectUtil.getFieldValue(parent, this.childrenField);
ReflectUtil.setFieldValue(apply, this.childrenField, oc);
return apply;
}
/**
* 将树扁平化
*
* @param list
* @param out
* @param <T>
*/
public static <T> void flatTree(List<T> list, List<T> out, String childrenField) {
list.forEach(tp -> {
List<T> chs = (List<T>) ReflectUtil.getFieldValue(tp, childrenField);
if (CollectionUtil.isNotEmpty(chs)) {
ReflectUtil.setFieldValue(tp, childrenField, null);
out.add(tp);
flatTree(chs, out, childrenField);
} else {
out.add(tp);
}
});
}
public static void main(String[] args) {
List<Node> list = new ArrayList<>();
Node p4 = new Node(4, "p2-1-1", 3, 3, new ArrayList<>());
Node p5 = new Node(5, "p2-1-1-1", 4, 4, new ArrayList<>());
Node p3 = new Node(3, "p2-1", 2, 1, new ArrayList<>());
Node p1 = new Node(1, "p1", 1, 0, new ArrayList<>());
Node p2 = new Node(2, "p2", 1, 0, new ArrayList<>());
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
list.add(p5);
List<Node> treeNode = TreeBuilderUtilTR.<Node>build().sourceList(list)
.withParent(node -> node.getLevel().equals(1))
.withChildrenLink((root, current) -> root.getId().equals(current.getParentId()))
.mapToObj(n -> {
return n;
});
treeNode.forEach(System.out::println);
}
}
import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
/**
* @Author tianxue
* @Date 2021/12/31 10:32 上午
*/
public class SimpleRetry<T> {
/**
* 最大尝试次数 默认 1 次
*/
private int maxCount = 1;
/**
* 每次请求的间隔时间 默认 5s
*/
private Duration intervalTime = Duration.ofSeconds(5);
private Class<?> exception = Exception.class;
/**
* 最大尝试次数 默认 1 次
*/
private Function<Integer, Object> onRetryHandel = i -> "";
public SimpleRetry<T> onRetry(Function<Integer, Object> onRetryHandel) {
this.onRetryHandel = onRetryHandel;
return this;
}
public SimpleRetry<T> withException(Class exception) {
this.exception = exception;
return this;
}
public SimpleRetry<T> withMaxCount(int maxCount) {
this.maxCount = maxCount;
return this;
}
public SimpleRetry<T> withIntervalTime(Duration intervalTime) {
this.intervalTime = intervalTime;
return this;
}
@FunctionalInterface
public interface SupplierThrow<T> {
/**
* Gets a result.
*
* @return a result
*/
T get() throws Exception;
}
/**
* 根据fuc的结果是否需要进行尝试
* 通用Retry执行器
*
* @param fuc 执行方法的主体
*/
public Optional<T> execute(SupplierThrow<T> fuc) {
int retry = 0;
do {
if (retry > 0) {
try {
TimeUnit.MILLISECONDS.sleep(this.intervalTime.toMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
try {
return Optional.ofNullable(fuc.get());
} catch (Exception e) {
if (this.exception.isAssignableFrom(e.getClass())) {
retry++;
this.onRetryHandel.apply(retry);
continue;
}
break;
}
} while (retry <= this.maxCount);
return Optional.empty();
}
public static void main(String[] args) {
Optional<String> execute = new SimpleRetry<String>()
.withMaxCount(2)
.withIntervalTime(Duration.ofSeconds(5))
.withException(Exception.class)
.execute(() -> {
if (Math.random() > 0.5) {
throw new Exception("123");
}
return "111";
});
execute.ifPresent(e -> {
System.out.println("**" + e);
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment