Java 8 лямбда-фильтрация на основе условий, а также порядка - PullRequest
0 голосов
/ 05 декабря 2018

Я пытался отфильтровать список по нескольким условиям, сортируя.

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;
        }
    }

Теперь, если у меня есть список этого, скажем

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.

Ответы [ 4 ]

0 голосов
/ 05 декабря 2018

Просто, чтобы смешать и объединить другие решения, вы можете сделать следующее:

Map<String, Student> nameToStudentMap = new HashMap<>();
Set<Student> finalListOfStudents = students.stream()
        .map(x -> nameToStudentMap.merge(x.getName(), x, (a, b) -> a.getAge() > b.getAge() ? a : b))
        .collect(Collectors.toSet());
0 голосов
/ 05 декабря 2018

Если вам нужна только отсортированная группировка, это довольно просто:

Map<String, List<Student>> collect = students.stream() // stream capabilities
        .sorted(Comparator.comparingInt(Student::getAge).reversed()) // sort by age, descending
        .collect(Collectors.groupingBy(Student::getName)); // group by name.

Вывод в сборе:

  • Prince = [Student [Age = 24, className = B], Имя = Принц]],
  • Смит = [Студент [Возраст = 24, имя класса = A, Имя = Смит]],
  • Джон = [Студент [Возраст = 30, имя_класса = A, Имя = Джон], Студент [Возраст = 24, имя_класса = A, Имя = Джон], Студент [Возраст = 20, Имя_класса = B, Имя = Джон]]
0 голосов
/ 05 декабря 2018

или без потоков:

Map<String, Student> map = new HashMap<>();
students.forEach(x -> map.merge(x.getName(), x, (oldV, newV) -> oldV.getAge() > newV.getAge() ? oldV : newV));
Collection<Student> max = map.values();
0 голосов
/ 05 декабря 2018

Использование коллектора toMap:

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

Объяснение

Мы используем эту перегрузку toMap:

toMap​(Function<? super T,? extends K> keyMapper,
      Function<? super T,? extends U> valueMapper,
      BinaryOperator<U> mergeFunction)
  • Student::getName выше - это функция keyMapper, используемая для извлечения значений для ключей карты.
  • Function.identity() выше - это функция valueMapper, используемая для извлечениязначения для значений карты, где Function.identity() просто возвращает элементы в источнике, который они сами, т.е. объекты Student.
  • BinaryOperator.maxBy(Comparator.comparingInt(Student::getAge)) выше - это функция слияния, используемая для «определения, какой объект Student будет возвращен вслучай ключевого столкновения, т. е. когда два заданных студента имеют одно и то же имя », в этом случае мы берем самое старое Student.
  • Наконец, вызов values() возвращает нам коллекцию студентов.

Эквивалентный код C #:

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

Объяснение (для тех, кто не знаком с .NET)

Мы используем этот метод расширения 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, используемая для извлечения значения в group by.
  • v => v выше - это elementSelector функция, используемая для извлечения значений, т.е. Student объекты сами по себе.
  • b.OrderByDescending(e => e.Age).Take(1) выше это resultSelector, что даетIEnumerable<Student>, представленный как b, принимает самого старшего ученика.
  • Наконец, мы применяем .SelectMany(x => x);, чтобы свести получившееся IEnumerable<IEnumerable<Student>> в IEnumerable<Student>.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...