0

I have a list of objects. Each object has three fields: id, secNumber and type. Type is enum which can have values 'new' or 'legacy'. Sometimes it happens that there are objects in that list which have the same secNumber a but different type.

in such a situation, I need to remove the one with type 'legacy'. How to do it using Java 8 streams?

2 Answers 2

3

use toMap with something like this:

Collection<T> result = list.stream()
    .collect(toMap(T::getSecNumber, 
            Function.identity(), 
             (l, r) -> l.getType() == Type.LEGACY ? r : l))
    .values();

where T is the class that contains secNumber, id etc.

  • The keyMapper (T::getSecNumber) extracts each secNumber from each object.
  • The valueMapper (Function.identity()) extracts the objects we want as the map values i.e. the objects from the source them selves.
  • The mergeFunction (l, r) -> is where we say " if two given objects have the same key i.e. getSecNumber then keep the one where their type is 'NEW' and discard the one with 'LEGACY'" and finally we call values() to accumulate the map values into a Collection.

Edit:

following @Tomer Aberbach's comment you may be looking for:

List<T> result = 
            list.stream()
                .collect(groupingBy(T::getSecNumber))
                .values()
                .stream()
                .flatMap(l -> l.stream().anyMatch(e -> e.getType() == Type.NEW) ?
                    l.stream().filter(e -> e.getType() != Type.LEGACY) :
                    l.stream())
                .collect(toList());

The first solution using toMap assumes there can't be multiple objects with the same secNumber and type.

Sign up to request clarification or add additional context in comments.

6 Comments

Maybe it's because it assumes there can't be multiple objects with the same secNumber and type? So if you had two objects of type NEW with the same secNumber it would chuck one of them.
@TomerAberbach true, edited to accommodate your comment.
@Aomine, I think it's not quite there because if you have a bunch of objects of only type Type.LEGACY for a secNumber you chuck them all. Check out my answer to see what I mean.
@TomerAberbach Right I see, +1 and btw I'll leave both solutions just in case they may want the first approach I've illustrated.
Thanks guys for your answers. I've used that second approach as first one is returning error that l is of type Object which does not have getType() method.
|
3

Assume objects is a List<ClassName> which has been declared and initialized:

List<ClassName> filteredObjects = objects.stream()
    .collect(Collectors.groupingBy(ClassName::getSecNumber))
    .values().stream()
    .flatMap(os -> os.stream().anyMatch(o -> o.getType() == Type.NEW) ?
        os.stream().filter(o -> o.getType() != Type.LEGACY) :
        os.stream()
    ).collect(Collectors.toList());

I made the assumption that objects of type Type.LEGACY should only be filtered out if there exists another object of type Type.NEW which has the same secNumber. I also made the assumption that you could have multiple objects of the same type and secNumber and that those may need to be retained.

Note that the collect(Collectors.groupingBy(ClassName::getSecNumber)) returns a map from whatever type secNumber is to List<ClassName> so calling values() on it returns a Collection<List<ClassName>> which represents a collection of the groupings of objects with the same secNumber.

The flatMap part takes each grouping by secNumber, checks if the grouping has at least one object of Type.NEW, and if so, filters out the objects of type Type.LEGACY, otherwise it just passes along the objects to be flattened into the final List<ClassName>. This is primarily so that if a grouping only has objects of type Type.LEGACY then they are not left out of the final collection.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.