如何在Java8中按流将Map对象上的对象按时间段求和?

时间:2019-05-24 02:05:59

标签: java

我有一个Map对象。 key是ID,值是Transaction的列表。下面是Transaction类代码:

public class Transaction {
    private double amount;
    private LocalDateTime timestamp;
...
}

Map transactions = new HashMap<String, List<Transaction>>();

// how to stream transactions here?

我正在尝试获取每个key在24小时内发生的交易总数。首先,我需要循环每个键的事务列表。然后根据时间戳将交易分组。然后将每个分组交易的值相加。

例如,地图对象具有以下值:

'012345': [ {'05-05-2019:10.00.00', 100}, {'05-05-2019:11.00.00', 100},{'05-05-2019:12.00.00', 100} ]
`678900`: [ {'05-06-2019:10.00.00', 100}, {'05-06-2019:11.00.00', 100},{'05-07-2019:10.30.00', 100} ]

它有两个键012345678900,每个键都有三个事务。密钥012345下的交易发生在24小时内,而678900下的交易则进行了2天。输出应为24小时窗口期间的总和。看起来像这样:

'012345': [300],
'678900': [200, 200]

678900下的三笔交易有两个24小时的窗口期。因此,它给出两个200的数量。中间交易有两个24小时的窗口期,因此需要两次计算。

以下是我的想法:

transactions.values().forEach(txnList -> {
            Map<Integer, DoubleSummaryStatistics> collect = txnList.stream().collect(Collectors.groupingBy(txn -> txn.getTimestamp().getHour() / 24, Collectors.summarizingDouble(Transaction::getAmount)));
        });

,但是没有返回正确的值。我不知道该怎么做。谁能指出我这样做的正确方法?

1 个答案:

答案 0 :(得分:0)

如果您愿意使用第三方库,则Eclipse-Collections中提供了一些API,这些API可以很好地完成您的工作。这适用于任何Java java.lang.Iterable。代码如下:

    Map<String, List<Transaction>> transactionsMap = getMapOfTransactionalData(...);
    final long currentTime = Instant.now().getEpochSecond();
    Map<String, Double> idTransactionSumMap = MapIterate.collect(transactionsMap, (id, transList) -> {
        Collection<Transaction> transactionsForTimeRange = Iterate.select(transList, transaction -> {
            // Implement your condition to compare time, below is just an example, you can define your range as well
            long transactionTime = transaction.getTimestamp().toEpochSecond(ZoneOffset.UTC);
            return transactionTime > currentTime - TimeUnit.HOURS.toMillis(24);
        });
        return Tuples.pair(id, Iterate.sumOfDouble(transactionsForTimeRange, Transaction::getAmount));
    });

如果您通过eclipse-collection使用MutableMap和MutableList,代码将类似于:

MutableMap<String, MutableList<Transaction>> transactionsMap = getMapOfTransactionalData(...);
long currentTime = Instant.now().getEpochSecond();
MutableMap<String, Double> idTransactionSumMap = transactionsMap.collect((id, transList) -> Tuples.pair(id, transList.select(transaction -> {
    // your condition to compare time
    long transactionTime = transaction.getTimestamp().toEpochSecond(ZoneOffset.UTC);
    return transactionTime > currentTime - TimeUnit.HOURS.toMillis(24);
}).sumOfDouble(Transaction::getAmount)));