从列表中检索多个次要事件

时间:2018-08-07 21:52:31

标签: java java-8 java-stream

我有一个自定义对象列表:

List<CustomObject> customObjects;

我想从中提取具有最早的datetime值设置的所有对象。

所以类看起来像这样:

class CustomObject {
   LocalDateTime date;

   public LocalDateTime getDateTime() {
       return date;
   }
}

并且我可以使用以下自定义比较器功能成功地在最早的日期中找到列表中的对象:

private static LocalDateTime getDate(CustomObject customObject) {
        return customObject.getDateTime();
}

CustomObject customObjectMin = customObjects.stream().
           min(Comparator.comparing(MyUtilClass::getDate));

但是,可以有多个具有相同日期的自定义对象,但是在这种情况下,似乎min无法获得多次出现。是否有一个简单的解决方案来查找设置了最早日期的列表中的所有对象?像这样:

List<CustomObject> customObjectsMin = customObjects.stream().
           minWithAllOccurences(Comparator.comparing(MyUtilClass::getDate));

2 个答案:

答案 0 :(得分:3)

您可以进行两个选择。

  • 找到最短日期的人
  • 找到那个日期的人

例如

LocalDate min = customObjects.stream()
                             .map(CustomObject::getDateTime)
                             .min(Comparator.naturalOrder());
List<CustomObject> objs = customObjects.stream()
                             .filter(c -> min.equals(c.getDateTime()))
                             .collect(Collectors.toList());

或者您可以使用Collectors.groupingBy进入TreeMap并获取第一个条目。

答案 1 :(得分:0)

除了Peter Lawrey的出色回答外,我想指出的是,可以用单个流执行此操作,同时避免将每个元素收集到TreeMap中的内存成本。怎么样?一种方法是使用reduce(),如下所示:

List<SampleJava> customObjectsMin = customObjects.stream()
        .reduce(new ArrayList<>(), // identity
        (List<SampleJava> list, SampleJava item) -> { // accumulate
            if(list.isEmpty() ||  getDate(item).compareTo(getDate(list.get(0))) < 0) {
                return new ArrayList<>(Arrays.asList(item));
            } else if(getDate(item).equals(getDate(list.get(0)))) {
                list.add(item);
            }
            return list;
        },
        (list1, list2) -> { // combine
            if(list1.isEmpty()) return list2; 
            if(list2.isEmpty()) return list1; 
            int cmp = getDate(list1.get(0)).compareTo(getDate(list2.get(0)));
            if(cmp < 0) return list1;
            if(cmp > 0) return list2;
            list1.addAll(list2);
            return list1;
        });