【问题标题】:How do I filter the list based on comparision within list elements in Java 8?如何根据 Java 8 中列表元素内的比较过滤列表?
【发布时间】:2018-07-11 10:35:53
【问题描述】:

我有一个

class MedicationPeriod {
    LocalDateTime startDate, endDate;
    //assume getters and setters
}

然后我有一个List<MedicationPeriod> medPrd = getMedPeriods();

medPrd 中的元素可能具有相同的 startDate。

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

示例:如果列表元素是:

1) startDate = 2018-Jan-1, endDate = 2018-Feb-25 // 25 天

2) startDate = 2018-Jan-1, endDate = 2018-Feb-20 // 20 天

3) startDate = 2018-Jan-5, endDate = 2018-Feb-25 // startDate 不同,我们不在乎

所以最终列表应该只有元素 1) 和 3)。元素 2 将被删除,因为具有相同 startDate 的其他 MedicationPeriod 具有更大的 endDate。

这是我获得结果的尝试(不愉快地工作):

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

我的要求:

  1. 我想要List<MedicationPeriod> 而不是Collection<MedicationPeriod>,因为我的解决方案是Collection<>

  2. 我想在不收集它们并使用 .values() 的情况下实现这一点,因为我可能会在流中进行进一步的转换并稍后收集它们。

假设我必须在过滤 MedicationPeriods 后进行一些测试,然后将其收集到:

class DateRange {
    LocalDate startDate, endDate;
}

如何只用一个终端操作来做到这一点?

【问题讨论】:

  • 我认为,应该可以用BinaryOperator.maxBy(Comparator.comparing(MedicationPeriod::getEndDate))替换(a,b) -> a.endDate.isAfter(b.endDate) ? a : b)

标签: collections filter java-8 java-stream


【解决方案1】:

您的代码没有任何问题。有用。只是做了一些重构

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

结合@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()));

【讨论】:

  • 感谢重构。我如何在中间流操作中实现这一点。如果我想进一步将此 MedicationPeriod 转换为 DateRange,然后收集到 List。我只想进行一个终端操作。
  • DateRange 类的外观如何。我可以相应地编辑我的答案。由于您获得了一个列表,因此您可以对其进行流式传输并使用 map 进行转换。不需要火箭科学
  • 假设 DateRange 如下:class DateRange{LocalDate startDate, endDate;} 但在收集之前不要转换它:-)
  • 抱歉没听懂。您可以使用这些详细信息编辑您的问题
  • 我们是否使用地图或其他一些数据结构在这里是最不重要的。但是对于您需要的逻辑,您必须进行终端操作并将其保存到一些数据结构中,然后继续前进
猜你喜欢
  • 2018-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-12
  • 1970-01-01
  • 2023-04-03
相关资源
最近更新 更多