Java 8 lambda过滤基于条件和顺序 [英] Java 8 lambda filtering based on condition as well as order

查看:487
本文介绍了Java 8 lambda过滤基于条件和顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图根据多个条件过滤列表,排序。

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

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

        public Student(int age, String className, String name) {
            Age = age;
            this.className = className;
            Name = name;
        }

        public int getAge() {
            return Age;
        }

        public void setAge(int age) {
            Age = age;
        }

        public String getClassName() {
            return className;
        }

        public void setClassName(String className) {
            this.className = className;
        }

        public String getName() {
            return Name;
        }

        public void setName(String name) {
            Name = name;
        }
    }

现在,如果我有一个清单,请说

Now if I have a list of that, say

List<Student> students = new ArrayList<>();
        students.add(new Student(24, "A", "Smith"));
        students.add(new Student(24, "A", "John"));
        students.add(new Student(30, "A", "John"));
        students.add(new Student(20, "B", "John"));
        students.add(new Student(24, "B", "Prince"));

我如何能够获得具有不同名称的最年长学生的名单?
在C#中,通过使用System.Linq GroupBy然后比较然后使用select进行展平,这将非常简单,我不太确定如何在Java中实现相同的效果。

How would I be able to get a list of the oldest students with a distinct name? In C# this would be quite simple by using System.Linq GroupBy then comparing and then flattening with select, I'm not too sure how I could achieve the same in Java.

推荐答案

使用 toMap 收藏家:

Use the toMap collector:

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

解释

我们正在使用的重载来映射

toMap​(Function<? super T,? extends K> keyMapper,
      Function<? super T,? extends U> valueMapper,
      BinaryOperator<U> mergeFunction)




  • 上面的学生:: getName keyMapper 用于提取地图键值的函数。

  • Function.identity()以上是 valueMapper 函数,用于提取映射值的值,其中 Function.identity()只返回元素他们自己的来源,即学生对象。

  • BinaryOperator.maxBy(Comparator.comparingInt(Student :: getAge))上面是合并函数,用于决定在一个关键的碰撞情况下返回哪个学生对象,即当两个给定的学生有同名在这种情况下,取最旧的学生

  • 最后,调用 values()向我们返回一系列学生。

    • 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.
    • 等效的C#代码为:

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

      解释(对于那些不熟悉.NET的人)

      Explanation (for those unfamiliar with .NET)

      我们正在使用 GroupBy

      We're using this extension method of GroupBy:

      System.Collections.Generic.IEnumerable<TResult> GroupBy<TSource,TKey,TElement,TResult> 
             (this System.Collections.Generic.IEnumerable<TSource> source, 
               Func<TSource,TKey> keySelector, 
               Func<TSource,TElement> elementSelector, 
           Func<TKey,System.Collections.Generic.IEnumerable<TElement>,TResult> resultSelector);
      




      • s => s.Name 上面是用于提取值的 keySelector 函数。

      • v => v 上面是 elementSelector 函数,用于提取值,即学生对象自我。

      • b.OrderByDescending(e => e.Age)。获取(1)以上是 resultSelector 给出 IEnumerable< Student> 表示为 b 取最年长的学生。

      • 最后,我们应用 .SelectMany(x => x); 来折叠生成的 IEnumerable< IEnumerable< Student>> 进入 IEnumerable< Student>

        • 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<Student> represented as b takes the oldest student.
        • Finally, we apply .SelectMany(x => x); to collapse the resulting IEnumerable<IEnumerable<Student>> into a IEnumerable<Student>.
        • 这篇关于Java 8 lambda过滤基于条件和顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆