首先测试bean类:
@Data
public class BeanTest1 {
private Integer id;
private Integer parentId;
private String name;
private List<BeanTest1> children = new LinkedList<>();
public BeanTest1(Integer id, Integer parentId, String name) {
this.id = id;
this.parentId = parentId;
this.name = name;
}
}
加入数据
List<BeanTest1> beanTest1List = new LinkedList<>();
beanTest1List.add(new BeanTest1(1,0,"1"));
beanTest1List.add(new BeanTest1(2,1,"2"));
beanTest1List.add(new BeanTest1(3,1,"3"));
beanTest1List.add(new BeanTest1(4,1,"4"));
beanTest1List.add(new BeanTest1(5,0,"5"));
beanTest1List.add(new BeanTest1(6,5,"6"));
beanTest1List.add(new BeanTest1(7,6,"7"));
Map<Integer, List<BeanTest1>> integerListMap = countChildren2(beanTest1List);
integerListMap.forEach((k,v) -> {
System.out.println(k+"---"+v);
});
一、只有父类包含子类,子类没有子类的情况:
递归算法:
Map<BeanTest1, List<BeanTest1>> result = new HashMap<>();
public Map<BeanTest1, List<BeanTest1>> countChildrenRecursive(List<BeanTest1> beanTest1List) {
for (BeanTest1 bean : beanTest1List) {
if (bean.getParentId() == null) {
continue;
}
if (!result.containsKey(bean)) {
result.put(bean, new ArrayList<>());
}
result.get(bean).addAll(countChildrenRecursive(bean.getChildren()).get(bean));
}
return result;
}
迭代算法:
Map<BeanTest1, List<BeanTest1>> result = new HashMap<>();
public Map<BeanTest1, List<BeanTest1>> countChildrenIterative(List<BeanTest1> beanTest1List) {
for (BeanTest1 bean : beanTest1List) {
if (bean.getParentId() == null) {
continue;
}
BeanTest1 parent = findParent(beanTest1List, bean.getParentId());
if (!result.containsKey(parent)) {
result.put(parent, new ArrayList<>());
}
result.get(parent).add(bean);
}
return result;
}
public BeanTest1 findParent(List<BeanTest1> beanTest1List, Integer parentId) {
for (BeanTest1 bean : beanTest1List) {
if (bean.getId().equals(parentId)) {
return bean;
}
}
return null;
}
二、不仅父类包含子类,子类也有子类的情况:
递归算法:
如果子类也有子类,可以在递归算法中继续调用自身,直到所有子类都遍历完为止。
Map<BeanTest1, List<BeanTest1>> result = new HashMap<>();
public Map<BeanTest1, List<BeanTest1>> countChildrenRecursive(List<BeanTest1> beanTest1List) {
for (BeanTest1 bean : beanTest1List) {
if (bean.getParentId() == null) {
continue;
}
BeanTest1 parent = findParent(beanTest1List, bean.getParentId());
if (!result.containsKey(parent)) {
result.put(parent, new ArrayList<>());
}
result.get(parent).add(bean);
if (!bean.getChildren().isEmpty()) {
countChildrenRecursive(bean.getChildren());
}
}
return result;
}
public BeanTest1 findParent(List<BeanTest1> beanTest1List, Integer parentId) {
for (BeanTest1 bean : beanTest1List) {
if (bean.getId().equals(parentId)) {
return bean;
}
}
return null;
}
在这里,我们首先判断子类是否有子类,如果有就继续调用countChildrenRecursive方法。
迭代算法
Map<BeanTest1, List<BeanTest1>> result = new HashMap<>();
Queue<BeanTest1> queue = new LinkedList<>();
public Map<BeanTest1, List<BeanTest1>> countChildrenIterative(List<BeanTest1> beanTest1List) {
for (BeanTest1 bean : beanTest1List) {
if (bean.getParentId() == null) {
queue.offer(bean);
}
}
while (!queue.isEmpty()) {
BeanTest1 parent = queue.poll();
if (!result.containsKey(parent)) {
result.put(parent, new ArrayList<>());
}
result.get(parent).addAll(parent.getChildren());
queue.addAll(parent.getChildren());
}
return result;
}
迭代算法中我们将父类加入队列中进行迭代遍历,遍历到的子类也加入队列中继续遍历,直到所有类都被遍历完为止。
这种方法有个缺点是需要使用额外的队列来存储遍历过的对象,会占用额外的空间。
另外,在这种情况下,我们需要确保 BeanTest1 类中有 getChildren() 方法,并且每个 BeanTest1 对象的 children 属性已经被初始化。
请注意:如果parentId=0的时候,会出现一个key为null,也就是0为父类的情况,实际应用中请自行忽略及更改
以上输出长这样:
null---[BeanTest1(id=1, parentId=0, name=1, children=null), BeanTest1(id=5, parentId=0, name=5, children=null)]
BeanTest1(id=6, parentId=5, name=6, children=null)---[BeanTest1(id=7, parentId=6, name=7, children=null)]
BeanTest1(id=1, parentId=0, name=1, children=null)---[BeanTest1(id=2, parentId=1, name=2, children=null), BeanTest1(id=3, parentId=1, name=3, children=null), BeanTest1(id=4, parentId=1, name=4, children=null)]
BeanTest1(id=5, parentId=0, name=5, children=null)---[BeanTest1(id=6, parentId=5, name=6, children=null)]
也有返回值是List的,最外层都是parentId为0的,然后数据存在children中
List<BeanTest1> result = new ArrayList<>();
public List<BeanTest1> countChildren(List<BeanTest1> beanTest1List) {
for (BeanTest1 bean : beanTest1List) {
if (bean.getParentId() == 0) {
result.add(bean);
} else {
BeanTest1 parent = findParent(beanTest1List, bean.getParentId());
parent.getChildren().add(bean);
}
}
return result;
}
public BeanTest1 findParent(List<BeanTest1> beanTest1List, Integer parentId) {
for (BeanTest1 bean : beanTest1List) {
if (bean.getId().equals(parentId)) {
return bean;
}
}
return null;
}