@Data
@ExcelIgnoreUnannotated
public class CourseVo {
private static final long serialVersionUID = 1L ;
private String courseId;
private String name;
private String type;
private String parentId;
private String sort;
private String remark;
private List < CourseVo > children;
}
import cn. hutool. core. collection. CollUtil ;
import cn. hutool. core. lang. tree. Tree ;
import cn. hutool. core. lang. tree. TreeNodeConfig ;
import cn. hutool. core. lang. tree. TreeUtil ;
import cn. hutool. core. lang. tree. parser. NodeParser ;
import com. corecode. common. utils. reflect. ReflectUtils ;
import lombok. AccessLevel ;
import lombok. NoArgsConstructor ;
import org. springframework. util. Assert ;
import java. util. * ;
import java. util. function. Function ;
import java. util. stream. Collectors ;
import java. util. stream. Stream ;
@NoArgsConstructor ( access = AccessLevel . PRIVATE)
public class TreeBuildUtils extends TreeUtil {
public static final TreeNodeConfig DEFAULT_CONFIG = TreeNodeConfig . DEFAULT_CONFIG. setNameKey ( "label" ) ;
public static < T , K > List < Tree < K > > build ( List < T > list, NodeParser < T , K > nodeParser) {
if ( CollUtil . isEmpty ( list) ) {
return null ;
}
K k = ReflectUtils . invokeGetter ( list. get ( 0 ) , "parentId" ) ;
return TreeUtil . build ( list, k, DEFAULT_CONFIG, nodeParser) ;
}
public static < T > List < T > buildTree ( List < T > list, Function < T , ? > key, Function < T , ? > parentKey,
Function < T , ? extends Comparable > sortKey, Consumers < T , T > consumer) {
if ( CollUtil . isEmpty ( list) ) {
return Collections . emptyList ( ) ;
}
Assert . notNull ( key, "父级被子级关联的字段不能为空" ) ;
Assert . notNull ( parentKey, "子级关联父级的字段不能为空" ) ;
Assert . notNull ( consumer, "消费函数不能为空" ) ;
List < T > tree = Collections . synchronizedList ( new ArrayList < > ( ) ) ;
Map < ? , List < T > > collect = Collections . synchronizedMap ( list. parallelStream ( )
. filter ( item -> Objects . nonNull ( parentKey. apply ( item) ) )
. collect ( Collectors . groupingBy ( parentKey) ) ) ;
list. parallelStream ( )
. filter ( m -> {
final boolean b = Objects . nonNull ( parentKey. apply ( m) ) && StringUtils . isNotEmpty ( ( String ) parentKey. apply ( m) ) ;
if ( ! b) {
tree. add ( m) ;
}
return b;
} )
. forEach (
node -> {
sortFunction ( sortKey, consumer, node, collect. get ( key. apply ( node) ) ) ;
}
) ;
Stream < T > peek = tree. parallelStream ( ) . peek ( node ->
sortFunction ( sortKey, consumer, node, collect. get ( key. apply ( node) )
) ) ;
return peek. collect ( Collectors . toList ( ) ) ;
}
private static < T > void sortFunction ( Function < T , ? extends Comparable > sortKey, Consumers < T , T > consumer, T node, List < T > children) {
if ( Objects . isNull ( children) ) {
return ;
}
if ( Objects . nonNull ( sortKey) ) {
try {
Comparator comparing = Comparator . comparing ( sortKey) ;
List < T > sort = CollUtil . sort ( children, comparing) ;
consumer. accept ( node, sort) ;
} catch ( NullPointerException e) {
consumer. accept ( node, children) ;
}
} else {
consumer. accept ( node, children) ;
}
}
@FunctionalInterface
public interface Consumers < T , N > {
void accept ( T m, List < N > n) ;
}
}
List < CourseVo > vos = this . queryList ( bo) ;
List < CourseVo > tree = TreeBuildUtils . buildTree ( vos, CourseVo :: getCourseId , CourseVo :: getParentId , CourseVo :: getSort , CourseVo :: setChildren ) ;