反射这块可以自己实现
Last active
June 24, 2022 03:27
-
-
Save itxve/a4a43a001cf54d98b3af908ae2e31bf0 to your computer and use it in GitHub Desktop.
一个从List构建到Tree的工具类
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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