Home > other >  Get Common elements and Difference between two Lists by a particular property using Streams
Get Common elements and Difference between two Lists by a particular property using Streams

Time:07-12

I have two lists of objects dbAssets and assetVOS.

I want common elements (and difference) by some property (getSecName() in my case) using streams.

I've tried the following:

dbAssets.stream().map(SomeClass::getSecName)
    .filter(dbAssetName -> assetVOS.stream()
            .map(SomeClass::getSecName)
            .anyMatch(assetVOSName -> dbAssetName.equals(assetVOSName)))
    .collect(Collectors.toList());

But I'm getting the following error:

Incompatible types. Required List<SomeClass> but 'collect' was inferred to R: no instance(s) of type variable(s) exist so that String conforms to SomeClass inference variable T has incompatible bounds: equality constraints: SomeClass lower bounds String

CodePudding user response:

Since you are mapping your SomeClass instances into Strings, your stream pipeline produces a List<String>, not a List<SomeClass>.

To get a List<SomeClass>, try something like this:

List<SomeClass> output = 
    dbAssets.stream()
            .filter(obj -> assetVOS.stream()
                                   .map(SomeClass::getSecName)
                                   .anyMatch(assetVOSName -> obj.getSecName ().equals(assetVOSName)))
            .collect(Collectors.toList());

CodePudding user response:

I want common elements (and difference)

If you want both: a list of elements with the second name is property which present in the assetVOS list and a list of those elements which names are not are not present, you can use collector partitioningBy() to do that in one iteration over the dbAssets list.

And instead of iterating over the list assetVOS multiple times to check if it contains an element with a particular name, we can store all the names from the assetVOS into a set, and then perform the checks against the set in a constant time.

That how it might look like:

List<SomeClass> dbAssets = // initializing the list
List<SomeClass> assetVOS = // initializing the list
        
Set<String> names = assetVOS.stream()
    .map(SomeClass::getSecName)
    .collect(Collectors.toSet());
        
Map<Boolean, List<SomeClass>> presentInAssetVOS = dbAssets.stream()
    .collect(Collectors.partitioningBy(
        user -> names.contains(user.getSecName())
    ));
    
List<SomeClass> isPresentInAssetVOS = presentInAssetVOS.get(true);
List<SomeClass> notPresentInAssetVOS = presentInAssetVOS.get(false);
  • Related