【问题标题】:Java 8 stream api key based merging基于 Java 8 流 api 键的合并
【发布时间】:2015-10-27 08:18:53
【问题描述】:

我最近开始学习流 API。 我正在尝试从以下代码中删除重复项。 是否可以使用基于Predicate 或条件的合并功能? (我也在考虑使用来自CollectorspartitioningBygroupingBy

BinaryOperator<LocalDateTime> latestDate = (p, a) -> a.isAfter(p) ? a : p;
BinaryOperator<LocalDateTime> earliestDate = (p, a) -> a.isBefore(p) ? a : p;


         Map<Status,LocalDateTime> latest = history.stream()
                    .filter(isNewOrOpen.negate())
                    .collect(toMap(History::getStatus,
                            History::getChangedtetme,
                            latestDate));

        Map<Status,LocalDateTime> earliest = history.stream()
                    .filter(isNewOrOpen)
                    .collect(toMap(History::getStatus,
                            History::getChangedtetme,
                            earliestDate));

            latest.putAll(earliest);

【问题讨论】:

  • 所以你有两个单独的列表,即historyhistoryGroup?
  • @TagirValeev 他们不应该,这是我的错字。改变了。谢谢!

标签: java merge java-8 java-stream


【解决方案1】:

如果我正确理解您的问题,isNewOrOpen 谓词使用History.getStatus(),并且您希望选择日期最早的历史项目作为新/打开状态,而选择日期最晚的历史项目作为其他状态。最好定义实现这个逻辑的Comparator(这里假设h1h2的状态相同):

Comparator<History> comparator = (h1, h2) -> isNewOrOpen.test(h1) ? 
    h2.getChangedtetme().compareTo(h1.getChangedtetme()):
    h1.getChangedtetme().compareTo(h2.getChangedtetme());

使用这个比较器,很容易定义收集器来解决你的任务:

Collector<History, ?, Map<Status, LocalDateTime>> collector
        = groupingBy(History::getStatus, 
                collectingAndThen(maxBy(comparator), 
                opt -> opt.get().getChangedtetme()));

注意collectingAndThen 的用法:maxBy 返回Optional&lt;History&gt;,我们要提取getChangedtetme()(不管它是什么意思)。

所以最后你可以直接使用这个收集器了:

Map<Status, LocalDateTime> result = history.stream().collect(collector);

latestDateearliestDate 似乎没有必要。

【讨论】:

    【解决方案2】:

    正如你所说,你可以使用 Collectors.partitioningBy 来做你想做的事。

    BinaryOperator<LocalDateTime> latestDate = (p, a) -> a.isAfter(p) ? a : p;
    
    Map<Boolean, Map<Status,LocalDateTime>> partitions = 
            history.stream()
                   .collect(partitioningBy(isNewOrOpen,
                                           toMap(History::getStatus,
                                           History::getChangedtetme,
                                           latestDate));
    
    Map<Status,LocalDateTime> latest = partitions.get(true);
    Map<Status,LocalDateTime> earliest = partitions.get(false);
    

    【讨论】:

    • 我认为latestDate 也可以表达为BinaryOperator.maxBy(Comparator.naturalOrder())
    • 抱歉,从我的列表中看不出来,我有两个 BinaryOpertaors(我已经添加了第二个)。这确实有道理,但我必须根据状态使用它们 - 最早用于新或打开,最新用于其他。
    猜你喜欢
    • 2018-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-03
    • 2015-10-20
    • 1970-01-01
    • 2019-09-24
    相关资源
    最近更新 更多