Home > Software engineering >  How to filter list based on custom criteria?
How to filter list based on custom criteria?

Time:10-18

I have a java list consisting of objects. Most of the objects have common fields and I need to keep just the one object from the list of candidates that have a specific field set. How can I achieve this? Example

class A{
  String field1;
  String field2;
  String field3;
  LocalDate dateField;

}

With the following values;

A first = new A("field1","field2","field3",null);
A second = new A("field1","field2","field3",LocalDate.now());
A third= new A("field1","field2","field3",LocalDate.now().plusMonths(3));
A forth= new A("4","5","6",LocalDate.now().plusMonths(3));
A fifth = new A("7","8","9",LocalDate.now().plusMonths(3));

I need to write a method that returns a list consisting of second, forth and fifth. So if field1 field2 and field3 are identical, I need to keep the minimum localdate field. How to achieve this?

CodePudding user response:

I understand you have a List<A> of objects of type A.

It seems want to filter the list, querying it for items A that match some requirement. What kinds of things you want to search when filtering that list isn't very clear.

 List<A> items = ...; // setup the items
 List<A> items_filtered = items.stream()
   .filter( x -> x.field1.equals("value") )
   .collect(Collectors.toList());
 List<A> items_filtered_2 = items.stream()
   .filter( x -> !x.field2.equals("other_value") )
   .collect(Collectors.toList());

These filters can be applied to any list, including list that is the result of a previous filter, or you can combine two checks in the same filter.

 List<A> fitlered_both = items.stream()
   .filter( x -> x.field1.equals("value") && !x.field2.equals("other_value") )
   .collect(Collectors.toList());

CodePudding user response:

You can try this

public static void main(String[] args) {
    A first = new A("field1","field2","field3",null);
    A second = new A("field1","field2","field3",LocalDate.now());
    A third= new A("field1","field2","field3",LocalDate.now().plusMonths(3));
    A forth= new A("4","5","6",LocalDate.now().plusMonths(3));
    A fifth = new A("7","8","9",LocalDate.now().plusMonths(3));

    List<A> collect = Stream.of(first, second, third, forth, fifth)
   .collect(
         Collectors.groupingBy(a -> Objects.hash(a.field1, a.field2, a.field3),
                    Collectors.minBy((o1, o2) -> {
                        if(o1 == null || o2 == null || o1.dateField == null || o2.dateField == null){
                            return 1;
                        }
                        return o1.dateField.compareTo(o2.dateField);
                    })))
            .values().stream().map(Optional::get).collect(Collectors.toList());
    System.out.println(collect);
}

You want to group the objects by similar objects first, Objects.hash(field1, field2, field3) will group objects based on field1, field2, and field3.

Next you want to sort the grouping using Localdate. Next, we collect the first elements of each group, which is our answer.

CodePudding user response:

I would suggest to write a comparator and sort the list using it. Then you will be able to retrieve all the desired objects within one pass

  • Related