日常のプロジェクトでは、親子構造のデータは、組織データなどのツリー構造データに構造化されることがよくあります。以前にインターネットで多くのソリューションを見たことがあり、構造化ツリー構造データフィールドがカプセル化された特定のクラスであることがわかりました。他の戻りフィールドを追加する場合は、自分でクラスにフィールドを追加する必要があります。そこで、私はあなたの前任者に基づいてジェネリックスを介して一連のソリューションを実装し、カスタムルートノードの判断をサポートしました。 ツリー構造に変換する必要があるクラスは、このインターフェイスを実装する必要があります。汎用Tは、エンティティクラスタイプの パブリックインターフェイスです。ITreeNode<T> { Object id(); Object parentId(); void addChild(T t); void removeChild(T t); List <T> children(); }
機能インターフェイスはルートノードを決定するために使用されます。デフォルトの判断があります。もちろん、実装をカスタマイズすることもできます。デフォルトのルートノードの判断方法では、parentIdがnullであるか、parentIdが指定された値と等しく、指定された値をに渡すことができます。
@FunctionalInterfaceの TreePredicate <T、R> {インタフェースパブリック ブールテスト(T、T、R、R) static <T extends ITreeNode、R> TreePredicate <T、R> rootNodePredicate(){ return(T t、R r)-> t.parentId()== null || t.parentId()。equals(r); } }
このクラスは、ツリー構造を構築するクラス、コアメソッドTreeBuilder(List <T> list、TreePredicate <T、R> predicate、R r)コンストラクターであり、コアアイデアは参照によって渡すことです。
public class TreeBuilder <T extends ITreeNode <T >> { private final LinkedHashMap <Object、T> treeNodesMap = new LinkedHashMap <>(); private final List <T> rootNodesList = new ArrayList <>(); / ** * @param list並列関係データ収集 * @ parampredicateルートノード を判断します * @ paramrルートノードであるかどうかを判断するためにparentIdと比較される値* @ param <R> parentIdと比較される値のタイプ * / public <R> TreeBuilder(List <T> list、TreePredicate <T、R> predicate、R r){ for(T t:list){ treeNodesMap.put(t.id()、t); } treeNodesMap.values()。forEach( v-> { if(!predicate.test(v、r)){ T p = treeNodesMap.get(v。parentId()); if(p!= null){ p.addChild(v); } } else { rootNodesList.add(v); } }); } public <R> TreeBuilder(List <T> list、R r){ this(list 、TreePredicate.rootNodePredicate()、r); } protected T getTreeNode(Object id){ return treeNodesMap.get(id); } public List <T> getRoot(){ return rootNodesList; } public String treeJsonData(){returnJSONObject 。 toJSONString(rootNodesList); } / **ノードのすべての子孫を取得します * @ paramid現在のノードID * @return List <TreeNode> if(parent!= null){ * / public List <T> getAllChildren(Object id){ List <T> allChildren = new ArrayList <>(16); T treeNode = getTreeNode(id); for(T t:treeNode.children()){ allChildren.add(t); allChildren.addAll(getAllChildren(t.id())); } return allChildren; } / **获取某一节点所有祖父节点 * / public List <T> getAllParent(Object id){ List <T> allParent = new ArrayList <>(16); T treeNode = getTreeNode(id); T親= treeNodesMap.get(treeNode.parentId()); allParent.add(parent); allParent.addAll(getAllParent((parent.id()))); } return allParent; } }
単純なテストクラス、ルートノードは空の文字列であると判断されます
@Data public classOrgDTOはITreeNode <OrgDTO> { @JSONField(ordinal = 1) private Stringid;を実装します。 @JSONField(ordinal = 2) プライベート文字列名; @JSONField(ordinal = 3) プライベート文字列parentId; @JSONField(ordinal = 4) private List <OrgDTO> children = new ArrayList <>(); @Override public Object id(){ return getId(); } @Override public Object parentId(){ return getParentId(); } @Override public void addChild(OrgDTO orgDTO){ children.add(orgDTO); } @Override public List <OrgDTO> children(){ 子を返す; } @Override public void removeChild(OrgDTO orgDTO){ children.remove(orgDTO); } public OrgDTO(String id、String parentId、String name){ this.id = id; this.parentId = parentId; this.name = name; } public static void main(String [] args){ List <OrgDTO> list = new ArrayList <>(); list.add(new OrgDTO( "1"、 ""、 "1")); list.add(new OrgDTO( "2"、 "1"、 "2")); list.add(new OrgDTO( "3"、 "2"、 "3")); list.add(new OrgDTO( "4"、"3"、 "4")); list.add(new OrgDTO( "5"、 "4"、 "5")); TreeBuilder <OrgDTO> tree = new TreeBuilder <>(list、 ""); System.out.println(tree.treeJsonData()); } }