Collections 在Java8中,如何基于列表元素内的比较过滤列表?

Collections 在Java8中,如何基于列表元素内的比较过滤列表?,collections,filter,java-8,java-stream,Collections,Filter,Java 8,Java Stream,我有一个 class MedicationPeriod { LocalDateTime startDate, endDate; //assume getters and setters } 然后我有一个列表medPrd=getMedPeriods() medPrd中的元素可能具有相同的起始日期 现在,我想过滤列表,以便对于具有相同startDate的元素,具有最大endDate的元素应该保留在列表中。也就是说,有最长的一天 示例:如果列表元素为: 1) 开始日期=2018年1月

我有一个

class MedicationPeriod {
    LocalDateTime startDate, endDate;
    //assume getters and setters
}
然后我有一个
列表medPrd=getMedPeriods()

medPrd
中的元素可能具有相同的起始日期

现在,我想过滤列表,以便对于具有相同startDate的元素,具有最大endDate的元素应该保留在列表中。也就是说,有最长的一天

示例:如果列表元素为:

1) 开始日期=2018年1月1日,结束日期=2018年2月25日//25天

2) 开始日期=2018年1月1日,结束日期=2018年2月20日//20天

3) startDate=2018-一月五日,endDate=2018-二月二十五日//startDate不一样,我们不在乎

因此,最终列表应该只包含元素1)和3)。元素2将被删除,因为具有相同起始日期的其他药物周期具有更大的结束日期

以下是我试图(不快乐地工作)获得结果的尝试:

mps.stream().collect(Collectors.toMap(MedicationPeriod::getStartDate, e -> e, (a,b) -> a.endDate.isAfter(b.endDate) ? a : b)).values();
我的要求:

mps.stream().collect(Collectors.toMap(MedicationPeriod::getStartDate, e -> e, (a,b) -> a.endDate.isAfter(b.endDate) ? a : b)).values();
  • 我想要
    列表
    而不是
    集合
    ,因为我的解决方案提供了
    集合

  • 我希望在不收集它们和使用
    .values()
    的情况下实现这一点,因为我可以在流中进行进一步的转换,稍后再收集它们

  • 假设我必须在过滤药物周期后进行一些测试,然后将其收集到:

    class DateRange {
        LocalDate startDate, endDate;
    }
    

    只有一个终端操作我怎么能做到这一点?

    您的代码没有问题。它起作用了。只是做了一些重构

     new ArrayList<>(medPrd.stream()
              .collect(Collectors.toMap(MedicationPeriod::getStartDate, Function.identity(), (a, b) -> a.endDate.isAfter(b.endDate) ? a : b))
              .entrySet()
              .stream()
              .map(entry -> new DateRange(entry.getValue().startDate, entry.getValue().getEndDate())).collect(Collectors.toList()));
    
    newarraylist(medPrd.stream()
    .collect(Collectors.toMap(MedicalationPeriod::getStartDate,Function.identity(),(a,b)->a.endDate.isAfter(b.endDate)?a:b))
    .entrySet()
    .stream()
    .map(entry->new DateRange(entry.getValue().startDate,entry.getValue().getEndDate()).collect(Collectors.toList());
    
    结合@Holger的建议,看起来

     new ArrayList<>(medPrd.stream()
          .collect(Collectors.toMap(MedicationPeriod::getStartDate, Function.identity(), BinaryOperator.maxBy(Comparator.comparing(MedicationPeriod::getEndDate))))
          .entrySet()
          .stream()
          .map(entry -> new DateRange(entry.getValue().startDate, entry.getValue().getEndDate())).collect(Collectors.toList()));
    
    newarraylist(medPrd.stream()
    .collect(Collectors.toMap(MedicalationPeriod::getStartDate,Function.identity(),BinaryOperator.maxBy(Comparator.comparing(MedicalationPeriod::getEndDate)))
    .entrySet()
    .stream()
    .map(entry->new DateRange(entry.getValue().startDate,entry.getValue().getEndDate()).collect(Collectors.toList());
    
    感谢您的重构。如何在中间流操作中实现这一点。如果我想进一步将这个MedicalationPeriod转换为DateRange,然后收集到列表中。我只想要一个终端操作。DateRange类是什么样子的。我可以相应地编辑我的答案。因为您得到的是一个列表,所以可以对其进行流式处理并使用map进行转换。不需要火箭科学让我们假设DateRange如下:类DateRange{LocalDate startDate,endDate;}但在收集之前不要转换它:-)抱歉,我不明白。您可以使用这些详细信息编辑您的问题,我们是否使用地图或其他数据结构,是否在此处最不重要。但是对于您需要的逻辑,您必须执行一个终端操作并将其保存到某个数据结构中,然后向前移动。我认为,应该可以替换
    (a,b)->a.endDate.isAfter(b.endDate)?a:b)
    with
    BinaryOperator.maxBy(Comparator.comparing(MedicalationPeriod::getEndDate))