Compare two different java collection objects with a common attribute using java streams api

78 Views Asked by At

I have two Sets containing 2 different objects

1. Set<A> 
2. Set<B>
    class A {
       private String id;
       private String name;
       private B objB;
    }
    
    class B {
       private String id;
       private String email;
    }

I want to check if any object of A in the first Set has the same "id" in the second Set B.

If it b.getId().contains(a.getId), then that B object will be set in A object.

objA.setB(objB);

Based on a Predicate how can we store B object into A based on matching "id" attribute value (using Java streams)?

2

There are 2 best solutions below

1
ruby yang On BEST ANSWER

First arrange all the id values from the B objects into a Map for fast access. Then loop the A objects, looking up each A object’s id for a match in the map.

Map<String,B> mapB = new HashMap<>();
for (B element : setB) {
    mapB.put(element.id, element);
}
setA.forEach (
    a ->{
        B b = mapB.get(a.getId());
        if(b!=null){
            a.setB(b);
        }
    }
);
2
Basil Bourque On

You can iterate through your master set using forEach.

aSet.forEach( … )

To assign a reference to the objB field, you’ll need to change the access level modifier appropriately, to something other than private.

For each of those A objects, we need to search the bSet for a match. Doing this search with a stream means we get an Optional as a result. We need to test each Optional to see if it carries a payload. If so, assign that payload’s B object to our A object.

I am guessing at the syntax here, untested code. I will try later. Hopefully this first draft can point you in the right direction.

aSet.forEach (
    a ->
        bSet
        .stream()
        .filter( b -> b.id.equals( a.id ) )
        .findAny()
        .ifPresent( b -> a.objB = b )
);

This approach is not optimized for performance. For better speed, see the Answer by ruby yang.