【问题标题】:Finding object in list by specific criteria按特定条件在列表中查找对象
【发布时间】:2021-08-07 12:47:37
【问题描述】:

我有一个列表,并且必须在那里找到特定的对象。 我必须按学生的平均标记值对列表进行排序,并创建函数 搜索具有第二高值的学生。如果它与其他学生重复,则函数将返回较年轻的学生。 此任务的另一个要求(要正确解决)是我无法创建任何对象。下面我留下了我正在使用的类的代码:

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

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

【问题讨论】:

  • “我无法创建任何对象”是什么意思?您可能正在排序/搜索的学生列表也是 Student 类的对象列表,不是吗?
  • 是的。我的意思是我不能创建额外的对象,比如变量/数组等。我必须对函数 args 中给出的列表进行所有操作。

标签: java sorting collections stream


【解决方案1】:

实现Comparable 而不是Comparator。

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

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

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

【讨论】:

  • 当心:我刚刚修正了比较器中的一个错字:我检查的是dateOfBirth = null 而不是other.dateOfBirth == null
【解决方案2】:

您应该能够通过提供一个自定义比较器来做到这一点,该比较器首先比较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 

【讨论】:

    【解决方案3】:

    我不会以这种方式在Student 课堂上实现Comparator&lt;Student&gt; 或Comparable&lt;Student&gt;,因为我不一定希望学生总是以这种方式进行比较。但我想这也取决于你的用例。

    你可以这样做:

    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)
    

    【讨论】:

      猜你喜欢
      • 2016-04-03
      • 1970-01-01
      • 1970-01-01
      • 2017-05-10
      • 1970-01-01
      • 2018-08-05
      • 2012-03-08
      • 1970-01-01
      • 2017-10-19
      相关资源
      最近更新 更多