2016-10-29 2 views
0

Ich experimentiere mit einem einfachen Programm, das ein Bankkonto erstellt und Transaktionen daran gebunden hat. Es funktioniert fehlerfrei, wenn ich primitive Typen verwende, jedoch habe ich eine Möglichkeit hinzugefügt, eine String-Operation hinzuzufügen (wie zB ERROR beim Zurückziehen), und jetzt weiß ich nicht, wie ich die Liste sortieren kann, damit die String-Operationen nicht erscheinen alle, wenn sie ausgedruckt, gefiltert oder am unteren Rand angezeigt werden, wenn sie sortiert sind.Vergleichen und sortieren von parametrisierten Typen in einer Liste?

vollständige Quellcode:

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

}

Antwort

0

Ihr Problem ist, dass Sie Äpfel mit Orangen vergleichen, wenn Sie Transaction<Double> mit Transaction<String> mischen. Ihr BankAccount kann nur einen Typ von Transaction enthalten. Sie sind entweder alle Transaction<Double> oder Transaction<String>.

Gerade jetzt, weil Sie Ihre BankAccount Klasse nicht parametrisiert haben behandelt es wie Transaction<Object>.

Die Lösung besteht darin, die BankAccount richtig zu parametrieren und entsprechend zu codieren. Hier ist eine Version, die mit BankAccount<String> codiert ist.

HINWEIS: Das Beispiel basiert auf String Vergleich von Zahlen, die keine solide Strategie ist. Ich habe den filter() Aufruf verschoben, um die "ERROR" Transaktionen zuerst zu entfernen. Dann sollten Sie in Betracht ziehen, in der Funktion, die Sie an comparing() übergeben, an Nummern zurück zu analysieren.

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

Wenn Sie Objekte mit verschiedenen Typen vergleichen (sortieren) möchten, warum schreiben Sie dann nicht einen eigenen Vergleicher dafür?

Beispiel:

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

dachte darüber nach, aber ich dachte auch bereits bestehende Möglichkeit zu vergleichen und/oder Art verschiedene Typen. Danke trotzdem für das Beispiel! – ForInfinity

Verwandte Themen