优化结构转换

This commit is contained in:
zhouhao
2017-05-31 11:22:53 +08:00
parent dc50ce01ba
commit a377fae108

View File

@@ -23,14 +23,14 @@ import org.hswebframework.web.id.IDGenerator;
import org.hswebframwork.utils.RandomUtil;
import org.hswebframwork.utils.StringUtils;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public interface TreeSupportEntity<PK> extends GenericEntity<PK> {
@@ -96,7 +96,11 @@ public interface TreeSupportEntity<PK> extends GenericEntity<PK> {
for (int i = 0; i < children.size(); i++) {
T child = children.get(i);
if (child instanceof SortSupportEntity && parent instanceof SortSupportEntity) {
((SortSupportEntity) child).setSortIndex(StringUtils.toLong(((SortSupportEntity) parent).getSortIndex() + "0" + (i + 1)));
Long index = ((SortSupportEntity) parent).getSortIndex();
if (null == index) {
((SortSupportEntity) parent).setSortIndex(index = 1L);
}
((SortSupportEntity) child).setSortIndex(new BigDecimal(index + "0" + (i + 1)).longValue());
}
child.setParentId(pid);
child.setPath(parent.getPath() + "-" + RandomUtil.randomChar(4));
@@ -111,54 +115,87 @@ public interface TreeSupportEntity<PK> extends GenericEntity<PK> {
* 集合转为树形结构,返回根节点集合
*
* @param dataList 需要转换的集合
* @param childAccepter 设置子节点回调
* @param <T> 树节点类型
* @param childConsumer 设置子节点回调
* @param <N> 树节点类型
* @param <PK> 主键类型
* @return 树形结构集合
*/
static <T extends TreeSupportEntity<PK>, PK> List<T> list2tree(Collection<T> dataList, BiConsumer<T, List<T>> childAccepter) {
return list2tree(dataList, childAccepter, (Function<RootNodePredicate<T, PK>, Predicate<T>>) predicate -> node -> node == null || predicate.getNode(node.getParentId()) == null);
static <N extends TreeSupportEntity<PK>, PK> List<N> list2tree(Collection<N> dataList, BiConsumer<N, List<N>> childConsumer) {
return list2tree(dataList, childConsumer, (Function<TreeHelper<N, PK>, Predicate<N>>) predicate -> node -> node == null || predicate.getNode(node.getParentId()) == null);
}
static <T extends TreeSupportEntity<PK>, PK> List<T> list2tree(Collection<T> dataList,
BiConsumer<T, List<T>> childAccepter,
Predicate<T> rootNodePredicate) {
return list2tree(dataList, childAccepter, (Function<RootNodePredicate<T, PK>, Predicate<T>>) predicate -> rootNodePredicate);
static <N extends TreeSupportEntity<PK>, PK> List<N> list2tree(Collection<N> dataList,
BiConsumer<N, List<N>> childConsumer,
Predicate<N> rootNodePredicate) {
return list2tree(dataList, childConsumer, (Function<TreeHelper<N, PK>, Predicate<N>>) predicate -> rootNodePredicate);
}
static <T extends TreeSupportEntity<PK>, PK> List<T> list2tree(Collection<T> dataList,
BiConsumer<T, List<T>> childAccepter,
Function<RootNodePredicate<T, PK>, Predicate<T>> predicateFunction) {
// id,obj
Map<PK, T> cache = new HashMap<>();
/**
* 列表结构转为树结构,并返回根节点集合
*
* @param dataList 数据集合
* @param childConsumer 子节点消费接口,用于设置子节点
* @param predicateFunction 根节点判断函数,传入helper,获取一个判断是否为跟节点的函数
* @param <N> 元素类型
* @param <PK> 主键类型
* @return 根节点集合
*/
static <N extends TreeSupportEntity<PK>, PK> List<N> list2tree(final Collection<N> dataList,
final BiConsumer<N, List<N>> childConsumer,
final Function<TreeHelper<N, PK>, Predicate<N>> predicateFunction) {
Objects.requireNonNull(dataList, "source list can not be null");
Objects.requireNonNull(childConsumer, "child consumer can not be null");
Objects.requireNonNull(predicateFunction, "root predicate function can not be null");
Supplier<Stream<N>> streamSupplier = () -> dataList.size() < 1000 ? dataList.stream() : dataList.parallelStream();
// id,node
Map<PK, N> cache = new HashMap<>();
// parentId,children
Map<PK, List<T>> treeCache = dataList.parallelStream()
Map<PK, List<N>> treeCache = streamSupplier.get()
.peek(node -> cache.put(node.getId(), node))
.collect(Collectors.groupingBy(TreeSupportEntity::getParentId));
Predicate<T> rootNodePredicate = predicateFunction.apply(new RootNodePredicate<T, PK>() {
Predicate<N> rootNodePredicate = predicateFunction.apply(new TreeHelper<N, PK>() {
@Override
public List<T> getChildren(PK parentId) {
public List<N> getChildren(PK parentId) {
return treeCache.get(parentId);
}
@Override
public T getNode(PK id) {
public N getNode(PK id) {
return cache.get(id);
}
});
return dataList.parallelStream()
return streamSupplier.get()
//设置每个节点的子节点
.peek(node -> childAccepter.accept(node, treeCache.get(node.getId())))
.peek(node -> childConsumer.accept(node, treeCache.get(node.getId())))
//获取根节点
.filter(rootNodePredicate)
.collect(Collectors.toList());
}
interface RootNodePredicate<T, PK> {
/**
* 树结构Helper
*
* @param <T> 节点类型
* @param <PK> 主键类型
*/
interface TreeHelper<T, PK> {
/**
* 根据主键获取子节点
*
* @param parentId 节点ID
* @return 子节点集合
*/
List<T> getChildren(PK parentId);
/**
* 根据id获取节点
*
* @param id 节点ID
* @return 节点
*/
T getNode(PK id);
}
}