按特定条件在列表中查找对象

Finding object in list by specific criteria

我有一个列表,必须在其中找到特定对象。 我必须按学生的平均分值对列表进行排序,并创建函数 搜索具有第二高价值的学生。如果它与其他学生重复,则较小的学生正在按功能 return 进行教育。 此任务的另一个要求(要正确解决)是我无法创建任何对象。下面我留下了我正在使用的 class 的代码:

import java.time.LocalDate;
import java.util.Comparator;
import java.util.List;

public class Student implements Comparator<Student>{
private String firstName;
private String lastName;
private LocalDate dateOfBirth;
private double averageMark;

public double getAverageMark() {
    return averageMark;
}

   
//function below must find student that I described upper. Currently 
//function is incomplete because I still try to find correct solution 
public static Student findSecondBestStudent(List<Student> students) {


    return students.stream().sorted(Comparator.reverseOrder());
}

@Override
public int compare(Student o1, Student o2) {
    return (int) (o1.getAverageMark() - o2.getAverageMark());
}
}

现在我确实尝试通过对流进行反向排序来解决这个问题,然后删除流的第一个值并比较流的下一个对象和 return 正确的对象。 我可以使用 for 循环解决它,但是这个解决方案与任务条件不匹配(需要创建对象)

实施 Comparable 而不是 Comparator

创建您的 compareTo 函数,使其按所需顺序对学生进行排序(反向)

对您的 stream 进行排序,跳过 1 个条目,return 下一个条目。

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

public class Student implements Comparable<Student> {
  private String firstName;
  private String lastName;
  private LocalDate dateOfBirth;
  private double averageMark;
  
  public Student(String firstName, String lastName, LocalDate dateOfBirth, double averageMark) {
    super();
    this.firstName = firstName;
    this.lastName = lastName;
    this.dateOfBirth = dateOfBirth;
    this.averageMark = averageMark;
  }

  public double getAverageMark() {
    return averageMark;
  }

  //function below must find student that I described upper. Currently 
  //function is incomplete because I still try to find correct solution 
  public static Student findSecondBestStudent(List<Student> students) {
    return students.stream().sorted().skip(1).findFirst().orElse(null);
  }

  @Override
  public int compareTo(Student other) {
    if (other == null)
      return 1;
    if (other.averageMark == averageMark) {
      if (other.dateOfBirth == null)
        return -1;
      return other.dateOfBirth.compareTo(dateOfBirth);
    }
    return Double.compare(other.averageMark, averageMark);
  }

  @Override
  public String toString() {
    return "Student [firstName=" + firstName + ", lastName=" + lastName + ", dateOfBirth=" + dateOfBirth
        + ", averageMark=" + averageMark + "]";
  }
  
  public static void main(String[] args) {
    final List<Student> students = new ArrayList<>(6);
    students.add(new Student("Peter", "Tibbitts", LocalDate.of(2001, 4, 6), 5));
    students.add(new Student("Leon", "Gaston", LocalDate.of(1951, 6, 17), 12));
    students.add(new Student("Eric", "Carter", LocalDate.of(1945, 12, 24), 9));
    students.add(new Student("Richard", "Heard", LocalDate.of(1984, 5, 9), 4));
    students.add(new Student("Frankie", "Bonner", LocalDate.of(1970, 4, 19), 10));
    students.add(new Student("Donald", "Pascal", LocalDate.of(2000, 3, 26), 10));
    
    final Student result = Student.findSecondBestStudent(students);
    System.out.println(result);
  }
  
}

我不会以这种方式在 Student class 中实施 Comparator<Student>Comparable<Student>,因为我不一定希望学生总是以这种方式进行比较。但我想这也取决于你的用例。

你可以这样做:

public static Student findSecondBestStudent(List<Student> students) {
    return students.stream()
            .sorted(Comparator.comparingDouble((Student o) -> o.averageMark)
                    .thenComparing(o -> o.dateOfBirth).reversed())
            .skip(1)
            .findFirst()
            .get();
}

输入:

List<Student> students = Arrays.asList(
        new Student("John", "Wall", LocalDate.of(2005, 1,1), 87),
        new Student("Russel", "Westbrook",  LocalDate.of(2001, 1,1), 88),
        new Student("Micheal", "Jordan",  LocalDate.of(2002, 1,1), 80),
        new Student("Kevin", "Durant",  LocalDate.of(2001, 1,1), 87),
        new Student("Carmelo", "Anthony",  LocalDate.of(2004, 1,1), 80)
);

输出:

Student(firstName=John, lastName=Wall, dateOfBirth=2005-01-01, averageMark=87.0)

您应该能够通过提供一个自定义比较器来做到这一点,该比较器首先比较 averageMarks,然后比较 dateOfBirth(如果发现相等):

public static Student findSecondBestStudent(List<Student> students) {
    return students.stream().sorted((o1, o2) -> {
        int marksCompareResult = Double.compare(o2.getAverageMark(), o1.getAverageMark());
        return marksCompareResult == 0 ?
                o1.getDateOfBirth().compareTo(o2.getDateOfBirth()) :
                marksCompareResult;
    }).collect(Collectors.toList()).get(1);
}

我用下面的代码测试了一下:

List<Student> students = new ArrayList<>();
students.add(new Student("Rupert", "Brik", LocalDate.of(1994, 12, 30), 51.1));
students.add(new Student("Marc", "Felix", LocalDate.of(1995, 6, 30), 59.1));
students.add(new Student("Max", "Peters", LocalDate.of(1997, 8, 21), 69.1));
students.add(new Student("Mike", "Ermentraut", LocalDate.of(1998, 9, 21), 76.1));
students.add(new Student("Bartosz", "Mazack", LocalDate.of(1999, 10, 12), 76.1));


Student secondBest = Student.findSecondBestStudent(students);
System.out.printf("%s %s %f ", secondBest.firstName, secondBest.lastName, secondBest.averageMark);

它打印:

Bartosz Mazack 76.100000