Java8 lambda 流删除对象的两个属性中具有 max 的对象

问题描述 投票:0回答:2

我有对象列表,任何对象都有两个日期属性 insertDate 和 updateDate 我需要找到在两个属性 insertDate 和 updateDate 之间具有绝对最大值的对象。 示例(列表对象具有属性):

-> insertDate = 2020-10-11 15:48 updateDate = 2020-11-11 15:48
   insertDate = null             updateDate = 2019-09-11 15:48
   insertDate = 2019-10-11 15:48 updateDate = null
   insertDate = null             updateDate = null
   insertDate = 2019-10-11 15:48 updateDate = 2019-11-11 10:48

因此箭头表示将被删除的List的对象。 我尝试了不同的方法:

  1. 使用流使用 sort(...).reverse 获取要从 insertDate 属性和 updateDate 属性中删除的最大值,然后比较两个值以找到最大值并使用结果对象来删除,但它太复杂且性能较低
  2. 我尝试使用集合的分组....但我找不到基于两个属性的最大值来删除的模式

等等等等..

重要:考虑到我们搜索 max 的 Date 属性可以为 null

有人可以提供一个高性能且优雅的解决方案吗? 它太复杂了,而且我对 lambda 的掌握不是很快......

非常感谢您的支持

lambda java-8 attributes java-stream max
2个回答
0
投票

这是一种可能性。我使用 LocalDateTime 完成此操作,而不是 Date,因为 Date 已过时。 应使用 java::time 包。 我出于演示目的更新了您的课程版本。 您需要用

MyObject
替换您的班级名称,才能使用您的数据。

数据。

List<MyObject> list = List.of(
        new MyObject("2020-10-11 15:48", "2020-11-11 15:48"),
        new MyObject(null, "2019-09-11 15:48"),
        new MyObject("2019-10-11 15:48", null),
        new MyObject(null, null),
        new MyObject("2019-10-11 15:48", "2019-11-11 10:48"));

比较器。

  • 其工作原理是获取每个对象日期对的持续时间,转换为毫秒,然后将每个对象与长值进行比较。
Comparator<MyObject> comp = (a,b)-> 
Long.compare(Duration.between(a.getInsertDate(),a.getUpdateDate())
        .toMillis(),
        Duration.between(b.getInsertDate(),b.getUpdateDate())
        .toMillis());

现在只需流式传输列表,过滤掉任何时候带有空值的对象。 结果返回具有最大持续时间的对象。 如果没有找到任何内容,则返回 null。

MyObject  result = list.stream()
        .filter(obj -> obj.getInsertDate() != null
                && obj.getUpdateDate() != null)
        .max(comp).orElse(null);

System.out.println(result);

此打印

2020-10-11 15:48 2020-11-11 15:48

为了完成,我提供了一个

Date
比较器来使用,因为你的对象中有
Date
字段。 只需将上一个流中的
dateComparator
替换为
comp
就可以正常工作了。

Comparator<MyObject> dateComparator = (a, b) -> Long.compare(
        Math.abs(a.getInsertDate().toInstant().toEpochMilli()-
                        a.getUpdateDate().toInstant().toEpochMilli()),                  
        Math.abs(b.getInsertDate().toInstant().toEpochMilli()-
                b.getUpdateDate().toInstant().toEpochMilli()));

对象类定义。

class MyObject {
    public LocalDateTime insertDate;
    public LocalDateTime updateDate;
    
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    public MyObject(String insertDate, String updateDate) {
        if (insertDate != null) {
            this.insertDate = LocalDateTime.parse(insertDate,dtf);
        }
        if (updateDate != null) {
            this.updateDate = LocalDateTime.parse(updateDate,dtf);
        }
    }
    
    public LocalDateTime getInsertDate() {
        return insertDate;
    }
    
    public LocalDateTime getUpdateDate() {
        return updateDate;
    }
    
    public String toString() {
        return insertDate.format(dtf) + " " + updateDate.format(dtf);
    }
}

0
投票
List<Element> elements;
Comparator<Date> dateComparator = (Date a, Date b) -> a == b ? 0
    : a == null ? -1 : b == null ? 1 : a.compareTo(b);
Optional<Element> maxElement = elements.stream().max((Element a, Element b) ->
    dateComparator.compare(
        dateComparator.compare(a.insertDate, a.updateDate) >= 0 ?
            a.insertDate : a.updateDate,
        dateComparator.compare(b.insertDate, b.updateDate) >= 0 ?
            b.insertDate : b.updateDate));
© www.soinside.com 2019 - 2024. All rights reserved.