我正在试验一个简单的程序,它创建了一个银行账户,并与之绑定了交易。当我使用基本类型时,它可以完美地工作,但是我包含了添加String操作的可能性(例如撤回时的ERROR),现在我不确定如何对列表进行排序,以便字符串操作在打印时根本不出现,如果过滤,或者在排序时出现在底部。
完整源代码:
public static void main(String[] args) {
BankAccount bankAccount = new BankAccount();
bankAccount.addTransaction(2, TransactionType.DEPOSIT);
bankAccount.addTransaction(100.66, TransactionType.DEPOSIT);
bankAccount.addTransaction(2, TransactionType.WITHDRAW);
bankAccount.addTransaction("ERROR", TransactionType.WITHDRAW);
List<Transaction> transactions = bankAccount.getTransactions();
List<Transaction> collect = transactions.stream()
//Error appears over here, probably due to wrong syntax of the two next lines.
.sorted(Comparator.comparing((Transaction tr) -> tr.getAmount()).reversed())
.filter(tr -> tr.getAmount() > 0)
.collect(toList());
collect.forEach(tr -> System.out.println(tr));
}
private static class BankAccount {
private List<Transaction> transactions = new ArrayList<>();
public <T> void addTransaction(T amount, TransactionType transactionType) {
Transaction transaction = new Transaction(amount, transactionType);
transactions.add(transaction);
//return 0;
}
public List<Transaction> getTransactions() {
return Collections.unmodifiableList(transactions);
}
@Override
public String toString() {
return "BankAccount{" +
"transactions=" + transactions +
'}';
}
}
private static class Transaction<T> {
private final T amount;
private final TransactionType transactionType;
private final Date dateCreated;
public Transaction(T amount, TransactionType transactionType) {
this.amount = amount;
this.transactionType = transactionType;
this.dateCreated = new Date();
}
public T getAmount() {
return amount;
}
public TransactionType getTransactionType() {
return transactionType;
}
public Date getDateCreated() {
return dateCreated;
}
@Override
public String toString() {
return "Transaction{" +
"amount=" + amount +
", transactionType=" + transactionType +
", dateCreated=" + dateCreated +
'}';
}
}
private static enum TransactionType {
DEPOSIT, WITHDRAW;
}
}
你的问题是,当你把Transaction<Double>
和Transaction<String>
混合在一起时,你是在比较苹果和橙子。你的BankAccount
只能容纳一种Transaction
。它们要么都是Transaction<Double>
要么都是Transaction<String>
。
现在,因为你没有你的BankAccount
类参数化,它对待它像Transaction<Object>
。
解决方案是适当地参数化BankAccount
和相应的代码。这是一个使用BankAccount<String>
编码的版本。
注意:示例依赖于String
数字比较,这不是一个合理的策略。我移动了filter()
调用,首先删除"ERROR"事务。然后,您将需要考虑解析回传递给comparing()
的函数中的数字。
public static void main(String[] args) {
BankAccount<String> bankAccount = new BankAccount<>();
bankAccount.addTransaction(Double.toString(2.00), TransactionType.DEPOSIT);
bankAccount.addTransaction(Double.toString(100.66), TransactionType.DEPOSIT);
bankAccount.addTransaction(Double.toString(2.00), TransactionType.WITHDRAW);
bankAccount.addTransaction("ERROR", TransactionType.WITHDRAW);
List<Transaction<String>> transactions = bankAccount.getTransactions();
List<Transaction<String>> collect = transactions.stream()
.filter(tr -> !tr.getAmount().equals("ERROR"))
.sorted(Comparator.<Transaction<String>, String> comparing(transaction -> transaction.getAmount()).reversed())
.collect(Collectors.toList());
collect.forEach(tr -> System.out.println(tr.getAmount() + " " + tr.getType().name()));
}
public static class BankAccount<T> {
private List<Transaction<T>> transactions = new ArrayList<>();
public void addTransaction(T amount, TransactionType transactionType) {
Transaction<T> transaction = new Transaction <>(amount, transactionType);
transactions.add(transaction);
}
public List<Transaction<T>> getTransactions() {
return Collections.unmodifiableList(transactions);
}
}
public static class Transaction<T> {
private final T amount;
private final TransactionType transactionType;
private final Date dateCreated;
public Transaction(T amount, TransactionType transactionType) {
this.amount = amount;
this.transactionType = transactionType;
this.dateCreated = new Date();
}
public T getAmount() {
return amount;
}
public TransactionType getType(){
return transactionType;
}
public Date getDateCreated(){
return dateCreated;
}
}
public enum TransactionType {
DEPOSIT, WITHDRAW;
}
如果你想比较(排序)不同类型的对象,为什么不为它编写自己的比较器呢?
的例子:
List<Transaction> collect = transactions.stream()
.sorted((t1, t2) -> {
if (t1.getAmount() instanceof String && t2.getAmount() instanceof String) {
return String.class.cast(t1.getAmount()).compareTo(String.class.cast(t2.getAmount()));
} else if (t1.getAmount() instanceof String) {
return 1;
} else if (t2.getAmount() instanceof String) {
return -1;
} else {
return new BigDecimal(t1.getAmount().toString()).compareTo(new BigDecimal(t2.getAmount().toString())); //ugly hack
}
})
.filter(tr -> tr.getAmount() instanceof Number && Number.class.cast(tr.getAmount()).doubleValue() > 0) //next ugly hack
.collect(Collectors.toList());
collect.forEach(System.out::println);