简体   繁体   中英

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

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

Since you are mapping your SomeClass instances into String s, 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());

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM