Можем ли мы использовать поток java в следующем сценарии? - PullRequest
0 голосов
/ 17 марта 2020

У меня есть класс скажем Student, который имеет поле marks типа Double. Я создаю list объектов ученика. Для каждого объекта учащегося в поле marks может быть установлено значение null или одно и то же значение в разных объектах учащегося. У меня есть проблема, когда я хочу вернуть один объект студента из этого list на основе следующих условий:

  1. , когда все учащиеся имеют одинаковый marks, а затем вернуть ноль.
  2. еще верните ученика с самым высоким marks.

Интересно, есть ли лучший подход, использующий java stream api, чтобы сделать это? Заранее спасибо.

Студенческий класс:

public class Student {
    private Double marks;

    public Double getMarks() {
        return marks;
    }

    public void setMarks(Double marks) {
        this.marks = marks;
    }

    @Override
    public String toString() {
        return "Student [marks=" + marks + "]";
    }

    public Student(Double marks) {
        super();
        this.marks = marks;
    }
}

Ответы [ 4 ]

4 голосов
/ 17 марта 2020

Используя Stream s, вы можете сделать это во время сбора до TreeMap и проверки lastEntry как в:

private Student highestMarkUniqueStudent(List<Student> studentList) {
    if(studentList.size() == 0) return null;
    if(studentList.size() == 1) return studentList.get(0);
    TreeMap<Integer, List<Student>> map = new TreeMap<>(studentList.stream()
            .collect(Collectors.groupingBy(Student::getMarks)));

    List<Student> highestMarkStudents = map.lastEntry().getValue();
    // only one highest or all same marks or more than one with highest mark
    return highestMarkStudents.size() == 1 ? highestMarkStudents.get(0) : null; 
}
1 голос
/ 17 марта 2020

Вы можете сделать так:

Действительно, используя TreeMap , вы получите самые высокие оценки в первой записи. поэтому, проверив его значение, вы можете вернуть желаемый результат. если все оценки имеют одинаковое значение, поэтому первая запись должна иметь значение более одного, и если у вас есть две или более наивысших оценки, то первая запись все еще имеет более одного объекта ученика в списке.

TreeMap<Integer, List<Student>> map = list.stream()
            .collect(Collectors.groupingBy(
                    Student::getMarks,
                    () -> new TreeMap<Integer, List<Student>>(Comparator.reverseOrder()),
                    Collectors.mapping(Function.identity(), Collectors.toList())));

Map.Entry<Integer, List<Student>> firstEntry = map.firstEntry();   
if (firstEntry.getValue().size() <= 1) {
     result = firstEntry.getValue().get(0);
}
0 голосов
/ 17 марта 2020

Вы можете работать с потоками, но вам понадобится вспомогательный объект, который сможет собирать ваши данные.

Теперь работу можно выполнять либо с сокращением, либо с сбором.

С сокращением вы бы сделали

students.stream().reduce(
       new Helper(),
       (helper, student) -> new Helper(helper, student));

class Helper {
    private Student bestStudent = null;
    private boolean different = false;
    public Helper() {
    }
    public Helper(Helper oldHelper, Student newStudent) {
        if (oldHelper.bestStudent == null) {
            bestStudent = newStudent;
        } else if (student.getMark() > oldHelper.bestStudent.getMark()) {
            different = true;
            bestStudent = student;
        } else if (student.getMark() < oldHelper.bestStudent.getMark()) {
            different = true;
        }
    }
    public Student getResult() {
        return different ? bestStudent : null;
    }
}

, но это создаст новый объект Helper для каждого ученика.

С коллекцией мы сделаем

students.stream().collect(Helper::new, Helper::accept, Helper::combine);

class Helper {
    private Student bestStudent = null;
    private boolean different = false;
    public Helper() {
    }
    public void accept(Student newStudent) {
        if (bestStudent == null) {
            bestStudent = newStudent;
        } else if (newStudent.getMark() > bestStudent.getMark()) {
            different = true;
            bestStudent = newStudent;
        } else if (newStudent.getMark() < bestStudent.getMark()) {
            different = true;
        }
    }
    public void combine() (Helper other) {
        if (bestStudent == null) {
            bestStudent = other.bestStudent;
            different = other.different;
        } else if (other.bestStudent != null && other.bestStudent.getMark() > bestStudent.getMark()) {
            different = true;
            bestStudent = other.bestStudent;
        } else if (other.bestStudent != null && other.bestStudent.getMark() < bestStudent.getMark()) {
            different = true;
        }
    }
    public Student getResult() {
        return different ? bestStudent : null;
    }
}

(Примечание: 1. Код не проверен, 2. части основы c logi c взяты из другой ответ .)

0 голосов
/ 17 марта 2020

Возможно, вам не нужны потоки. Отсортируйте список самых высоких оценок, если первые 2 совпадают, верните null, в противном случае верните первого ученика.

students.sort(Comparator.comparing(Student::getMarks).reversed());
boolean firstTwoHaveSameMarks = students.get(0).getMarks().equals(students.get(1).getMarks());
return firstTwoHaveSameMarks ? null : students.get(0);

Если 2 или более учеников имеют одинаковую наивысшую оценку, возвращается значение NULL, в противном случае возвращается ученик.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...