Home > Back-end >  Find elements in N-nested list and remove by specific property
Find elements in N-nested list and remove by specific property

Time:10-05

I'm trying to find and remove from a main object a certain number of sub//sub/sub//..(unknown nested level) elements. My situation is like this:

Root object:

public class Root {
    public int id;
    public int type;
    public String name;
    public List<Son> sons;
    ....
}

The main object (Root) has a list of Son that can have N nested lists of Son objects. Son object shares the same 3 variables names like root, plus other properties. Since I'm not able to know how deep nesting would be, I'm trying to find a way to find inside this nested Son objects, the multiple elements I want to remove that matches a specified property (int type==1).

I've tried with stream, but maybe I'm not capable enough to fit the right commands upon the code. Something like this:

List<Son> firstNode = root.getSons();

firstNode.stream()
        .forEach(c -> {
            if(c.geType()==1){
                firstNode.remove(c);
                logger.info("###############################>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" c.getName());
            }
});

However, this doesn't work.

I've tried with a while too, counting the deepest node of the object, but nodes may vary from subnode to subnode.

Any suggestions?

Trying to make you understand more the situation, I've made a diagram about how the object may be and where the type==1 are: https://i.imgur.com/az3iCRj.png

CodePudding user response:

Because that the number is not known , you need to use a recursive method to visit all the Tree.

Recursion is the technique of making a function call itself. This technique provides a way to break complicated problems down into simple problems which are easier to solve.

you need to fix a return condition first : for example if ( listOfSon.isEmpty()) return;

And then you need to do your business logic. After that the method need to call itself for all the Sons like that you garantee that your method will visit all existent node.

you can search for : recursion in java , Traversing through all nodes of a Tree in java . that will really give you a great idea about what you need

You may change the class Node to extends from the class Root to avoid writing another conditions

  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);
            }
        }
    }
}

Be carefull with deleting element from an ArrayList when iterating the ArrayList because it can cause a ConcurrentModificationException.

CodePudding user response:

Ok, try this. I had to make some assumptions. It will remove all of a given type except the root. Also, you should make the root an instance of Son for this to work. You don't really need a separate root class.

Simply call this with the root instance of Son and the type to be removed.

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);
           }
        }
    }
}
  • Related