我们可以在下面的场景中使用java流吗



我有一个类,比如Student,它有一个类型为Double的字段marks。我正在创建学生对象的list。每个学生对象可以将marks字段设置为null,或者在不同的学生对象中设置为相同的值。我有一个问题,基于以下条件,我想从list返回一个学生对象:

  1. 当所有学生都有相同的marks时,则返回null
  2. 其余为CCD_ 8最高的返校生

我想知道是否有更好的方法使用java流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;
}
}

使用Streams,您可以在收集到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; 
}

您可以这样做:

事实上,通过使用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);
}

您可以使用流,但您需要一个能够收集数据的助手对象。

现在的工作要么可以通过减少,要么可以通过收集来完成。

有了折扣,你就可以做

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。部分基本逻辑取自另一个答案。(

您可能不需要流。对列表中得分最高的第一名进行排序,如果前两名相同,则返回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);

如果两个或两个以上的学生有相同的最高分数,则返回null,否则返回该学生。

最新更新