【问题标题】:How to find Max Date in List<Object>?如何在 List<Object> 中找到 Max Date?
【发布时间】:2014-01-08 12:27:17
【问题描述】:

考虑一个类User

public class User{
  int userId;
  String name;
  Date date;
}

现在我有一个大小为 20 的 List&lt;User&gt;,如何在不使用手动迭代器的情况下在列表中找到 最大日期

【问题讨论】:

  • 你的问题我不清楚。你能详细说明一下吗?
  • 使用自定义比较器对列表进行排序并获取第一个结果。
  • “手动迭代器”是什么意思。 Collections.max(yourList, yourComparator) 算不算“手动”?
  • 我试过使用比较器!它工作正常!但我正在寻找类似 lambdaj 方法但不是 lambdaj 的东西!
  • 如果您要求我们向您推荐工具或库,那么您的问题与 SO 无关(请查看第 5 点 here

标签: java collections


【解决方案1】:

由于您要求使用 lambda,因此您可以在 Java 8 中使用以下语法:

Date maxDate = list.stream().map(u -> u.date).max(Date::compareTo).get();

或者,如果您有日期的吸气剂:

Date maxDate = list.stream().map(User::getDate).max(Date::compareTo).get();

【讨论】:

  • 谢谢您,也为我完成了这项工作!此解决方案避免使用Comparator,这可能很烦人,因为它无法识别Stream 中的对象类型。
  • 您需要先使用地图才能获取日期流
  • 使用 orElse(null) 然后 .get(); 是一种更安全的方法
  • 我通过搜索类似问题发现了这一点,但在您的示例中,我需要具有最大日期的用户。对于这种情况,还有另一件好事:Optional&lt;User&gt; user = users.stream().max(Comparator.comparing(User::getDate));
  • 如果您想要具有最大日期的对象而不仅仅是日期本身,您可以这样做:User user = Collections.max(list, Comparator.comparing(User::getDate))
【解决方案2】:

对接受的答案的一个小改进是进行空检查并获得完整的对象。

public class DateComparator {

public static void main(String[] args) throws ParseException {
    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");

    List<Employee> employees = new ArrayList<>();
    employees.add(new Employee(1, "name1", addDays(new Date(), 1)));
    employees.add(new Employee(2, "name2", addDays(new Date(), 3)));
    employees.add(new Employee(3, "name3", addDays(new Date(), 6)));
    employees.add(new Employee(4, "name4", null));
    employees.add(new Employee(5, "name5", addDays(new Date(), 4)));
    employees.add(new Employee(6, "name6", addDays(new Date(), 5)));
    System.out.println(employees);
    Date maxDate = employees.stream().filter(emp -> emp.getJoiningDate() != null).map(Employee::getJoiningDate).max(Date::compareTo).get();
    System.out.println(format.format(maxDate));
    //Comparator<Employee> comparator = (p1, p2) -> p1.getJoiningDate().compareTo(p2.getJoiningDate());
    Comparator<Employee> comparator = Comparator.comparing(Employee::getJoiningDate);
    Employee maxDatedEmploye = employees.stream().filter(emp -> emp.getJoiningDate() != null).max(comparator).get();
    System.out.println(" maxDatedEmploye : " + maxDatedEmploye);

    Employee minDatedEmployee = employees.stream().filter(emp -> emp.getJoiningDate() != null).min(comparator).get();
    System.out.println(" minDatedEmployee : " + minDatedEmployee);

}

public static Date addDays(Date date, int days) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(date);
    cal.add(Calendar.DATE, days); // minus number would decrement the days
    return cal.getTime();
}
}

你会得到以下结果:

 [Employee [empId=1, empName=name1, joiningDate=Wed Mar 21 13:33:09 EDT 2018],
Employee [empId=2, empName=name2, joiningDate=Fri Mar 23 13:33:09 EDT 2018],
Employee [empId=3, empName=name3, joiningDate=Mon Mar 26 13:33:09 EDT 2018],
Employee [empId=4, empName=name4, joiningDate=null],
Employee [empId=5, empName=name5, joiningDate=Sat Mar 24 13:33:09 EDT 2018],
Employee [empId=6, empName=name6, joiningDate=Sun Mar 25 13:33:09 EDT 2018]
]
2018-03-26
 maxDatedEmploye : Employee [empId=3, empName=name3, joiningDate=Mon Mar 26 13:33:09 EDT 2018]

 minDatedEmployee : Employee [empId=1, empName=name1, joiningDate=Wed Mar 21 13:33:09 EDT 2018]

更新:如果列表本身为空怎么办?

        Date maxDate = employees.stream().filter(emp -> emp.getJoiningDate() != null).map(Employee::getJoiningDate).max(Date::compareTo).orElse(new Date());
    System.out.println(format.format(maxDate));
    Comparator<Employee> comparator = Comparator.comparing(Employee::getJoiningDate);
    Employee maxDatedEmploye = employees.stream().filter(emp -> emp.getJoiningDate() != null).max(comparator).orElse(null);
    System.out.println(" maxDatedEmploye : " + maxDatedEmploye);

【讨论】:

    【解决方案3】:
    Comparator<User> cmp = new Comparator<User>() {
        @Override
        public int compare(User user1, User user2) {
            return user1.date.compareTo(user2.date);
        }
    };
    
    Collections.max(list, cmp);
    

    【讨论】:

      【解决方案4】:
      LocalDate maxDate = dates.stream()
                                  .max( Comparator.comparing( LocalDate::toEpochDay ) )
                                  .get();
      
      LocalDate minDate = dates.stream()
                                  .min( Comparator.comparing( LocalDate::toEpochDay ) )
                                  .get();
      

      【讨论】:

        【解决方案5】:

        只需使用 Kotlin!

        val list = listOf(user1, user2, user3)
        val maxDate = list.maxBy { it.date }?.date
        

        【讨论】:

          【解决方案6】:

          不言自明的风格

          import static java.util.Comparator.naturalOrder;
          ...
          
              list.stream()
                  .map(User::getDate)
                  .max(naturalOrder())
                  .orElse(null)          // replace with .orElseThrow() is the list cannot be empty
          

          【讨论】:

            【解决方案7】:

            故障排除风格

            你不应该直接调用 .get() 。 Stream::max 返回的可选,旨在从 .orElse... 内联处理中受益。

            如果您确定您的参数的大小为 2+:

            list.stream()
                .map(u -> u.date)
                .max(Date::compareTo)
                .orElseThrow(() -> new IllegalArgumentException("Expected 'list' to be of size: >= 2. Was: 0"));
            

            如果支持空列表,则返回一些默认值,例如:

            list.stream()
                .map(u -> u.date)
                .max(Date::compareTo)
                .orElse(new Date(Long.MIN_VALUE));
            

            致谢:@JimmyGeers,@assylias 来自已接受的答案。

            【讨论】:

              猜你喜欢
              • 2015-12-10
              • 2017-03-02
              • 1970-01-01
              • 2020-03-07
              • 2021-12-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-02-28
              相关资源
              最近更新 更多