2016-10-29 29 views
0

我正在試驗一個簡單的程序,該程序創建一個銀行賬戶並且有與之相關的交易。它在我使用基本類型時完美地工作,但是我包括添加一個String操作的可能性(例如退出時的錯誤),現在我不確定如何對列表排序,以便字符串操作不會出現在全部打印出來,如果過濾,或者如果排序出現在底部。比較和排列列表中的參數化類型?

完整的源代碼:

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; 
} 

}

回答

0

你的問題是,你是比較蘋果和橘子,當你與Transaction<String>混合Transaction<Double>。您的BankAccount只能容納一種類型的Transaction。它們全部是Transaction<Double>Transaction<String>

現在,因爲您沒有參數化BankAccount類,所以它將它視爲Transaction<Object>

解決方案是正確地參數化BankAccount並進行相應的編碼。這是一個使用BankAccount<String>編碼的版本。

注意:該示例是依靠String比較數字,這不是一個合理的策略。我移動filter()調用以首先刪除「錯誤」事務。然後,您將需要考慮解析回傳遞給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; 
} 
0

如果要比較(排序)具有不同類型的對象,爲什麼不爲例如編寫它自己的比較器?

例子:

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); 
+0

想過這個問題,但我還以爲已經有現有的方法來比較和/或種類不同的類型。儘管如此,謝謝你的例子! – ForInfinity