修改 API,使 TreeBuilder 实例可以复用。

dev
ZhouXY108 2024-03-02 14:48:19 +08:00
parent 5cee71a342
commit 5d0af2dad5
3 changed files with 28 additions and 22 deletions

View File

@ -81,6 +81,13 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10.1</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -11,32 +11,29 @@ import java.util.stream.Collectors;
import xyz.zhouxy.plusone.commons.collection.CollectionTools; import xyz.zhouxy.plusone.commons.collection.CollectionTools;
public class TreeBuilder<T, TSubTree extends T, TIdentity> { public class TreeBuilder<T, TSubTree extends T, TIdentity> {
private final Collection<T> nodes;
private final Function<T, TIdentity> identityGetter; private final Function<T, TIdentity> identityGetter;
private final Function<T, Optional<TIdentity>> parentIdentityGetter; private final Function<T, Optional<TIdentity>> parentIdentityGetter;
private final BiConsumer<TSubTree, T> addChildrenMethod; private final BiConsumer<TSubTree, T> addChildMethod;
public TreeBuilder(Collection<T> nodes, Function<T, TIdentity> identityGetter, public TreeBuilder(Function<T, TIdentity> identityGetter, Function<T, Optional<TIdentity>> parentIdentityGetter,
Function<T, Optional<TIdentity>> parentIdentityGetter, BiConsumer<TSubTree, T> addChildren) { BiConsumer<TSubTree, T> addChild) {
this.nodes = nodes;
this.identityGetter = identityGetter; this.identityGetter = identityGetter;
this.parentIdentityGetter = parentIdentityGetter; this.parentIdentityGetter = parentIdentityGetter;
this.addChildrenMethod = addChildren; this.addChildMethod = addChild;
} }
public List<T> buildTree() { public List<T> buildTree(Collection<T> nodes) {
Map<TIdentity, T> identityNodeMap = CollectionTools.toHashMap(nodes, identityGetter); Map<TIdentity, T> identityNodeMap = CollectionTools.toHashMap(nodes, identityGetter);
List<T> result = this.nodes.stream() List<T> result = nodes.stream()
.filter(node -> !this.parentIdentityGetter.apply(node).isPresent()) .filter(node -> !this.parentIdentityGetter.apply(node).isPresent())
.collect(Collectors.toList()); .collect(Collectors.toList());
for (T node : this.nodes) { nodes.forEach(node -> parentIdentityGetter.apply(node).ifPresent(parentIdentity -> {
Optional<TIdentity> parentIdentity = parentIdentityGetter.apply(node); if (identityNodeMap.containsKey(parentIdentity)) {
if (parentIdentity.isPresent() && identityNodeMap.containsKey(parentIdentity.get())) { @SuppressWarnings("unchecked")
@SuppressWarnings("all") TSubTree parentNode = (TSubTree) identityNodeMap.get(parentIdentity);
TSubTree parentNode = (TSubTree) identityNodeMap.get(parentIdentity.get()); addChildMethod.accept(parentNode, node);
addChildrenMethod.accept(parentNode, node);
} }
} }));
return result; return result;
} }
} }

View File

@ -8,12 +8,17 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.gson.Gson;
import lombok.ToString; import lombok.ToString;
class TreeBuilderTests { class TreeBuilderTests {
private static final Logger log = LoggerFactory.getLogger(TreeBuilderTests.class); private static final Logger log = LoggerFactory.getLogger(TreeBuilderTests.class);
private final TreeBuilder<Menu, MenuList, String> treeBuilder = new TreeBuilder<>(
Menu::getMenuCode,
Menu::getParentMenuCode,
MenuList::addChild);
@Test @Test
void testBuildTree() { void testBuildTree() {
@ -31,13 +36,10 @@ class TreeBuilderTests {
MenuItem.of("C", "C2", "二级菜单C2", "/c/c2"), MenuItem.of("C", "C2", "二级菜单C2", "/c/c2"),
MenuItem.of("C", "C3", "二级菜单C3", "/c/c3") MenuItem.of("C", "C3", "二级菜单C3", "/c/c3")
); );
List<Menu> menuTree = new TreeBuilder<>(
menus, List<Menu> menuTree = treeBuilder.buildTree(menus);
Menu::getMenuCode, log.info("menuTree: {}", new Gson().toJson(menuTree));
Menu::getParentMenuCode,
MenuList::addChild)
.buildTree();
log.info("menuTree: {}", menuTree);
} }
} }