我有一个这样的类
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