如何将映射对象与前一个对象的计算值结转



我有一个这样的类

class Transaction{
long id;
String type;
long quantity;
double amount;
}

我想把它转换成下面的

class TransactionDTO{
long id;
String type;
long quantity;
double amount;
double total;
}

假设输入如下

Transaction( id=1, type=buy, quantity=5, amount=5)
Transaction( id=1, type=buy, quantity=2, amount=3)
Transaction( id=1, type=buy, quantity=3, amount=6)

应该输出如下(quantity*amount adds when buy subtract when sell with previous amount)

Transaction( id=1, type=buy, quantity=5, amount=5, total=25)
Transaction( id=1, type=sell, quantity=2, amount=3, total=19)
Transaction( id=1, type=buy, quantity=3, amount=6, total=37)

我可以用for循环轻松地做到这一点。但我想知道lambda是否可以做到这一点。

特别希望使用先前计算的total与基于Transaction type的下一个元素。

那么这是可以做到的吗?如果是,那怎么做?

你可以这样做:

public List<TransactionDTO> getTransaction() {
double[] temporaryTotal = new double[1];
List<Transaction> transactionList = Arrays.asList(
new Transaction(1, "buy", 5, 5),
new Transaction(1, "sell", 2, 3),
new Transaction(1, "buy", 3, 6)
);
return transactionList.stream()
.map(
transaction -> new TransactionDTO(
transaction.getId(),
transaction.getType(),
transaction.quantity,
transaction.getAmount(),
calculate(transaction, temporaryTotal[0])
)
)
.peek(transaction -> temporaryTotal[0] = transaction.getTotal())
.collect(Collectors.toList());
}
private double calculate(final Transaction transaction, final double total){
if (transaction.getType().equals("buy")){
return total + (transaction.getQuantity() * transaction.getAmount());
}
return total - (transaction.getQuantity() * transaction.getAmount());
}

由于变量total不是最终的或有效的最终的,我们可以使用一个名为temporaryTotal的元素的数组。

输出是:

[TransactionDTO(id=1, type=buy, quantity=5, amount=5.0, total=25.0),
TransactionDTO(id=1, type=sell, quantity=2, amount=3.0, total=19.0),
TransactionDTO(id=1, type=buy, quantity=3, amount=6.0, total=37.0)]

似乎Transaction的流应该由id分组,TransactionDTO应该提供一个合并功能,根据type添加/减去数量,金额和总数:

class TransactionDTO {
long id;
String type;
long quantity;
double amount;
double total;
public TransactionDTO (Transaction t) {
this.id = t.id;
this.type = t.type;
int sign = "buy".equals(type) ? 1 : "sell".equals(type) ? -1 : 0;

this.amount = sign * t.amount;
this.quantity = sign * t.quantity;
this.total = sign * t.amount * t.quantity;
}
public TransactionDTO merge(TransactionDTO t) {
this.type = t.type; // store last type

int sign = "buy".equals(type) ? 1 : "sell".equals(type) ? -1 : 0;

this.amount += t.amount;
this.quantity += t.quantity;
this.total += sign * t.amount * t.quantity;
return this;
}
}

则可以使用Collectors.toMap检索TransactionDTO的列表,然后转换映射值:

List<Transaction> transactionList = Arrays.asList(
new Transaction(1, "buy", 5, 5),
new Transaction(1, "sell", 2, 3),
new Transaction(1, "buy", 3, 6),
new Transaction(2, "buy", 2, 4),
new Transaction(3, "sell", 1, 5)
);
List<TransactionDTO> totals = new ArrayList<>(
transactionList.stream()
.collect(Collectors.toMap(
Transaction::getId, // key
TransactionDTO::new,
TransactionDTO::merge,
LinkedHashMap::new // keep insertion order
))
.values()
);
totals.forEach(System.out::println); // assuming that TransactionDTO overrides toString

输出:

id: 1|type: buy|quantity: 6|amount: 8.0|total: 37.0
id: 2|type: buy|quantity: 2|amount: 4.0|total: 8.0
id: 3|type: sell|quantity: -1|amount: -5.0|total: -5.0

最新更新