Java 8 lambda filtering based on condition as well as order

后端 未结 4 703
清酒与你
清酒与你 2021-01-01 13:36

I was trying to filter a list based on multiple conditions, sorting.

class Student{
        private int Age;
        private String className;
        privat         


        
4条回答
  •  一生所求
    2021-01-01 14:06

    Use the toMap collector:

    Collection values = students.stream()
                    .collect(toMap(Student::getName,
                            Function.identity(),
                            BinaryOperator.maxBy(Comparator.comparingInt(Student::getAge))))
                    .values();
    

    Explanation

    We're using this overload of toMap:

    toMap​(Function keyMapper,
          Function valueMapper,
          BinaryOperator mergeFunction)
    
    • Student::getName above is the keyMapper function used to extract the values for the map keys.
    • Function.identity() above is the valueMapper function used to extract the values for the map values where Function.identity() simply returns the elements in the source them selves i.e. the Student objects.
    • BinaryOperator.maxBy(Comparator.comparingInt(Student::getAge)) above is the merge function used to "decide which Student object to return in the case of a key collission i.e. when two given students have the same name" in this case taking the oldest Student .
    • Finally, invoking values() returns us a collection of students.

    The equivalent C# code being:

    var values = students.GroupBy(s => s.Name, v => v,
                              (a, b) => b.OrderByDescending(e => e.Age).Take(1))
                          .SelectMany(x => x);
    

    Explanation (for those unfamiliar with .NET)

    We're using this extension method of GroupBy:

    System.Collections.Generic.IEnumerable GroupBy 
           (this System.Collections.Generic.IEnumerable source, 
             Func keySelector, 
             Func elementSelector, 
         Func,TResult> resultSelector);
    
    • s => s.Name above is the keySelector function used to extract the value to group by.
    • v => v above is the elementSelector function used to extract the values i.e. the Student objects them selves.
    • b.OrderByDescending(e => e.Age).Take(1) above is the resultSelector which given an IEnumerable represented as b takes the oldest student.
    • Finally, we apply .SelectMany(x => x); to collapse the resulting IEnumerable> into a IEnumerable.

提交回复
热议问题