2016-10-29 26 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