Home > Back-end >  How to remove from list if list based on condition
How to remove from list if list based on condition

Time:10-21

I have a list of objects like this:

MyObject {

   Date date;
   int value;
}

I want to iterate the list and only keeps the objects where the dates differ. If there are two objects with the same date then I want to keep the object with the bigger value. Can this be achieved by using streams and predicates somehow?

CodePudding user response:

Yes, you can use stream to filter distinct elements:

public class MyObject {
    
    private final LocalDate date;
    
    private final int value;
    
    public MyObject(LocalDate date, int value) {
        this.date = date;
        this.value = value;
    }
    
    public final LocalDate getDate() {
        return date;
    }
    
    public final int getValue() {
        return value;
    }
    
    @Override
    public String toString() {
        return "[date="   date   ", value="   value  "]";
    }
}

To get distinct elements you can do:

public static Collection<MyObject> getDistinct(List<MyObject> list) {
    return list.stream().collect(
            Collectors.groupingBy(MyObject::getDate, 
                    Collectors.collectingAndThen(
                            Collectors.maxBy(Comparator.comparingInt(MyObject::getValue)), 
                            Optional::get)))
            .values();
}

Then:

List<MyObject> list = List.of(new MyObject(LocalDate.of(2021, 1, 1), 1),
            new MyObject(LocalDate.of(2021, 1, 1), 2),
            new MyObject(LocalDate.of(2022, 2, 2), 2));
    
Collection<MyObject> distinct = getDistinct(list);
    
distinct.forEach(System.out::println);

Output:

[date=2022-02-02, value=2]
[date=2021-01-01, value=2]

Note: I would use LocalDate instead of Date

CodePudding user response:

You should use Map and Map.merge() instread of Stream.

record MyObject(Date date, int value) {}

public static void main(String[] args) {
    List<MyObject> list = List.of(
        new MyObject(new Date(0), 0),
        new MyObject(new Date(0), 1),
        new MyObject(new Date(1000), 2));

    Map<Date, MyObject> map = new LinkedashMap<>();
    for (MyObject e : list)
        map.merge(e.date(), e, (a, b) -> a.value() > b.value() ? a : b);
    list = new ArrayList<>(map.values());

    for (MyObject e : list)
        System.out.println(e);
}

output:

MyObject[date=Thu Jan 01 09:00:00 JST 1970, value=1]
MyObject[date=Thu Jan 01 09:00:01 JST 1970, value=2]
  • Related