Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find the hierarchy

Tags:

java

java-8

Let's consider a class in java

class Entity  {

Integer id;
Integer parentId;

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public Integer getParentId() {
    return parentId;
}

public void setParentId(Integer parentId) {
    this.parentId = parentId;
}


}
 }

Consider parentId like the foreign key(relates to id to another object).

Now I created 6 objects and put some values.

Entity e1 = new Entity();
    e1.setId(400);

    Entity e2 = new Entity();
    e2.setId(300);
            e2.setParentId(400);

    Entity e3 = new Entity();
    e3.setId(200);
    e3.setParentId(300);

    Entity e4 = new Entity();
    e4.setId(100);
            e4.setParentId(200);

    Entity e5 = new Entity();
    e5.setId(50);
            e5.setParentId(100);

    Entity e6 = new Entity();
    e6.setParentId(50);

Now I want to obtain the hierarchy of objects. That means If I give id, I should get the complete parent hierarchy and child hierarchy.

for eg: if I give 100 as id(entity: e4), I should get the parent hierarchy:- e4,e3,e2,e1 child hierarchy:- e4,e5,e6

Explanation:- for parent hierarchy:- we should add the initial e4 object first. then we will find the object whose iD is same as that of e4's parentId.(here e3) the process continues untill, the parentid is null for child hierarchy:- we should add the initial e4 object first. then we will find the object whose parentId is same as that of e4's id. (here e5)the process continues untill, the parentid is null

Solution by me for parent hierarchy:-

 List<Entity> parent = new ArrayList<Entity>();

    Entity ent = list.stream().filter(e -> e.getId() == 100).findFirst()
            .get(); // // 100 input id value

    parent.add(ent);

    Integer parentId = ent.getParentId();

    while (parentId != null) {

        int search = parentId;
        Entity newEntity = list.stream().filter(e -> e.getId() == search)
                .findFirst().get();

        parent.add(newEntity);
        parentId = newEntity.getParentId();
    }

for child hierarchy:

    Entity entnew = list.stream().filter(e -> e.getId() == 100).findFirst()
            .get(); // 100 input id value



    child.add(entnew);


    Integer idNew = entnew.getId();


    while (idNew != null) {

    int searchNew = idNew;

    Entity newEnt = list.stream().filter(f -> f.getParentId()!= null && f.getParentId() == searchNew)
            .findFirst().get();

    child.add(newEnt);
    idNew = newEnt.getId();

    }

I found this method to solve the scenario, But I want a more efficent solution in java 8 using its core concepts to solve this.

like image 248
Manu Joy Avatar asked Jul 14 '15 12:07

Manu Joy


People also ask

How do you get a SQL hierarchy?

The anchor member of the CTE is the first SELECT statement. By doing this, you select the root of the hierarchy; it's the basis on which the recursive query will work its magic and find all other levels of the hierarchy. This statement selects all the columns from the table employee .

What is a hierarchy table?

A hierarchy table specifies a hierarchy of terms (such as drugs and events) available for selecting criteria for data mining results before viewing them. A hierarchy table has no effect on the generation of statistical results for a run.

What is SQL Server hierarchy?

Hierarchical data is defined as a set of data items that are related to each other by hierarchical relationships. Hierarchical relationships exist where one item of data is the parent of another item.


1 Answers

I've found a more Java8-ish solution, with a smell of functional programming.

Given your six entities (please note that I've set the Id for e6, otherwise we get a NullPointerException):

Entity e1 = new Entity();
e1.setId(400);

Entity e2 = new Entity();
e2.setId(300);
e2.setParentId(400);

Entity e3 = new Entity();
e3.setId(200);
e3.setParentId(300);

Entity e4 = new Entity();
e4.setId(100);
e4.setParentId(200);

Entity e5 = new Entity();
e5.setId(50);
e5.setParentId(100);

Entity e6 = new Entity();
e6.setId(25); // this Id must be set, or we'll get a NPE
e6.setParentId(50);

And a list containing them:

List<Entity> list = new ArrayList<>();
list.add(e1);
list.add(e2);
list.add(e3);
list.add(e4);
list.add(e5);
list.add(e6);

Then, for parents hierarchy:

Function<Integer, Entity> byId = 
    id -> list.stream()
        .filter(e -> e.getId().equals(id))
        .findFirst()
        .orElse(null);

Entity parentsSeed = byId.apply(100); // e4

UnaryOperator<Entity> nextParent = 
    e -> e == null ? e : byId.apply(e.getParentId());

List<Entity> parents = 
    Stream.iterate(parentsSeed, nextParent)
        .limit(list.size())
        .filter(Objects::nonNull)
        .collect(Collectors.toList()); // [e4, e3, e2, e1]

And for children hierarchy:

Entity childrenSeed = byId.apply(100); // e4

Function<Integer, Entity> byParentId = 
    id -> list.stream()
        .filter(e -> id.equals(e.getParentId()))
        .findFirst()
        .orElse(null);

UnaryOperator<Entity> nextChild = 
    e -> e == null ? e : byParentId.apply(e.getId());

List<Entity> children = 
    Stream.iterate(childrenSeed, nextChild)
        .limit(list.size())
        .filter(Objects::nonNull)
        .collect(Collectors.toList()); // [e4, e5, e6]

The idea is to use the Stream.iterate() method, by creating a stream by means of a "functional" iteration.

For parents, I've created a UnaryOperator (a function) that, given an Entity, returns either its parent Entity or null; for children, I've created a UnaryOperator that, given an Entity, returns either its child Entity or null.

To perform those two searches, I've used another Function that simply searches the list by id and parentId, respectively.

like image 94
fps Avatar answered Oct 03 '22 22:10

fps