在 N 嵌套列表中查找元素并按特定 属性 删除
Find elements in N-nested list and remove by specific property
我正在尝试从主对象中查找并删除一定数量的子//sub/sub//..(未知嵌套级别)元素。我的情况是这样的:
根对象:
public class Root {
public int id;
public int type;
public String name;
public List<Son> sons;
....
}
主对象(Root)有一个Son列表,可以有N个嵌套的Son对象列表。
Son 对象共享相同的 3 个变量名称,如 root,以及其他属性。
因为我不知道嵌套有多深,所以我试图找到一种方法来找到这个嵌套的 Son 对象,我想删除的多个元素与指定的 属性 (int type= =1).
我试过使用流,但也许我没有足够的能力在代码中加入正确的命令。
像这样:
List<Son> firstNode = root.getSons();
firstNode.stream()
.forEach(c -> {
if(c.geType()==1){
firstNode.remove(c);
logger.info("###############################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"+c.getName());
}
});
然而,这不起作用。
我也尝试了一段时间,计算对象的最深节点,但节点可能因子节点而异。
有什么建议吗?
为了让您了解更多情况,我制作了一个图表,说明对象可能是什么以及 type==1 在哪里:
https://i.imgur.com/az3iCRj.png
因为不知道数目,需要用递归的方法访问所有的树
递归是使函数调用自身的技术。此技术提供了一种将复杂问题分解为更容易解决的简单问题的方法。
您需要先修复一个 return 条件:例如
如果 ( listOfSon.isEmpty()) return;
然后您需要执行业务逻辑。
之后,该方法需要为所有 Sons 调用自身,您保证您的方法将访问所有存在的节点。
可以搜索:java中的递归,java中遍历一棵树的所有节点。这会让你真正了解你需要什么
您可以将 class 节点更改为从 class 根 扩展以避免写入另一个条件
static void removeNode(Root r) {
if (r.sons!=null && !r.sons.isEmpty()) {
for (Son s : r.sons) {
if (s.type == 1) {
removeNode(s);
}
}
for (Son s : r.sons) {
if (s.type == 1) {
r.sons.remove(s);
}
}
}
}
在迭代 ArrayList 时小心删除 ArrayList 中的元素,因为它可能导致 ConcurrentModificationException。
好的,试试这个。我不得不做出一些假设。它将删除除根之外的所有给定类型。此外,您应该使 root 成为 Son 的一个实例,这样它才能工作。你真的不需要一个单独的根 class.
只需用 Son 的根实例和要删除的类型调用它。
public static void remove(Son son, int type) {
if (son == null) {
return;
}
Iterator<Son> iter = son.sons.iterator();
while(iter.hasNext()) {
Son s = iter.next();
if (s.type == type) {
iter.remove();
} else {
if (s.sons != null) {
remove(s, type);
}
}
}
}
我正在尝试从主对象中查找并删除一定数量的子//sub/sub//..(未知嵌套级别)元素。我的情况是这样的:
根对象:
public class Root {
public int id;
public int type;
public String name;
public List<Son> sons;
....
}
主对象(Root)有一个Son列表,可以有N个嵌套的Son对象列表。 Son 对象共享相同的 3 个变量名称,如 root,以及其他属性。 因为我不知道嵌套有多深,所以我试图找到一种方法来找到这个嵌套的 Son 对象,我想删除的多个元素与指定的 属性 (int type= =1).
我试过使用流,但也许我没有足够的能力在代码中加入正确的命令。 像这样:
List<Son> firstNode = root.getSons();
firstNode.stream()
.forEach(c -> {
if(c.geType()==1){
firstNode.remove(c);
logger.info("###############################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"+c.getName());
}
});
然而,这不起作用。
我也尝试了一段时间,计算对象的最深节点,但节点可能因子节点而异。
有什么建议吗?
为了让您了解更多情况,我制作了一个图表,说明对象可能是什么以及 type==1 在哪里: https://i.imgur.com/az3iCRj.png
因为不知道数目,需要用递归的方法访问所有的树
递归是使函数调用自身的技术。此技术提供了一种将复杂问题分解为更容易解决的简单问题的方法。
您需要先修复一个 return 条件:例如 如果 ( listOfSon.isEmpty()) return;
然后您需要执行业务逻辑。 之后,该方法需要为所有 Sons 调用自身,您保证您的方法将访问所有存在的节点。
可以搜索:java中的递归,java中遍历一棵树的所有节点。这会让你真正了解你需要什么
您可以将 class 节点更改为从 class 根 扩展以避免写入另一个条件
static void removeNode(Root r) {
if (r.sons!=null && !r.sons.isEmpty()) {
for (Son s : r.sons) {
if (s.type == 1) {
removeNode(s);
}
}
for (Son s : r.sons) {
if (s.type == 1) {
r.sons.remove(s);
}
}
}
}
在迭代 ArrayList 时小心删除 ArrayList 中的元素,因为它可能导致 ConcurrentModificationException。
好的,试试这个。我不得不做出一些假设。它将删除除根之外的所有给定类型。此外,您应该使 root 成为 Son 的一个实例,这样它才能工作。你真的不需要一个单独的根 class.
只需用 Son 的根实例和要删除的类型调用它。
public static void remove(Son son, int type) {
if (son == null) {
return;
}
Iterator<Son> iter = son.sons.iterator();
while(iter.hasNext()) {
Son s = iter.next();
if (s.type == type) {
iter.remove();
} else {
if (s.sons != null) {
remove(s, type);
}
}
}
}