2017-02-08 2 views
2

Ich versuche, zwei Listen von Büchern zu verwenden, die zwei verschiedene Leute gelesen und verglichen haben. Wenn das a Book (das ist ein Konstruktor, der aus einem String-Titel und einem String-Autor besteht) in der ersten Liste gleich einem der Bücher in der anderen Liste ist, füge ich es zu einer commonBooks-Liste hinzu. Dies ist, was ich so weit gekommen, aber ich halte diesen Vorschlag bekommen: „return-Anweisung hinzufügen“ oder „Änderung ungültig“Java 8 ArrayList Gleichheit

hier ist, was ich bisher:

public static ArrayList<Book> commonBooks(Person a, Person b) { 

    ArrayList<Book> personA = a.getRead(); 
    ArrayList<Book> personB = b.getRead(); 
    ArrayList<Book> sameBooks = new ArrayList<Book>(); 

    if (personA.size() < personB.size()) { 
     for (int i = 0; i < personA.size(); i++) { 
      Book ndx = personA.get(i); 
      if (personB.contains(ndx)) { 
       sameBooks.add(ndx); 
      } else if (personB.size() < personA.size()) { 
       for (int i1 = 0; i1 < personB.size(); i1++) { 
        Book ndx1 = personB.get(i1); 
        if (personB.contains(ndx1)) { 
         sameBooks.add(ndx1); 
        } else if (personB.size() < personA.size()) { 
         for (int i2 = 0; i1 < personB.size(); i2++) { 
          Book ndx2 = personB.get(i2); 
          if (personB.contains(ndx2)) { 
           sameBooks.add(ndx2); 
          } 

         } 
        } else { 
         return sameBooks; 
        } 

       } 
      } 
     } 
    } else { 
     return sameBooks; 
    } 

} 
+0

Jeder Zustand in Ihrem Programm einen Wert zurückgeben muß. Andernfalls müssen Sie am Ende einen außerhalb der bedingten Blöcke zurückgeben. Dies ist nur eine Möglichkeit sicherzustellen, dass ein Wert unabhängig von der erfüllten Bedingung immer zurückgegeben wird. Dies gilt für eine Methode, die erwartet, dass ein Wert zurückgegeben wird. Oder entfernen Sie alle return-Anweisungen und markieren Sie die Methode als void, wie vom Compiler vorgeschlagen :) – Prathap

Antwort

1

Dies ist, was ich so weit gekommen, aber ich halte diesen Vorschlag bekommen: „add return-Anweisung“ oder „Änderung ungültig“

Nicht alle logischen Ströme in Ihrer Methode Rückkehr der angegebene Rückgabetyp (ArrayList<Book>) in Ihrer Methodensignatur. In Ihrer if-Anweisung gibt es einige Flüsse, die Sie korrigieren müssen, um zurückzukehren.

public static ArrayList<Book> commonBooks(Person a, Person b) { 

ArrayList<Book> personA = a.getRead(); 
ArrayList<Book> personB = b.getRead(); 
ArrayList<Book> sameBooks = new ArrayList<Book>(); 

if (personA.size() < personB.size()) { 
    for (int i = 0; i < personA.size(); i++) { 
     Book ndx = personA.get(i); 
     if (personB.contains(ndx)) { 
      sameBooks.add(ndx); 
     } else if (personB.size() < personA.size()) { 
      for (int i1 = 0; i1 < personB.size(); i1++) { 
       Book ndx1 = personB.get(i1); 
       if (personB.contains(ndx1)) { 
        sameBooks.add(ndx1); 
       } else if (personB.size() < personA.size()) { 
        for (int i2 = 0; i1 < personB.size(); i2++) { 
         Book ndx2 = personB.get(i2); 
         if (personB.contains(ndx2)) { 
          sameBooks.add(ndx2); 
         } 

        } 
       } else { 
        //return sameBooks; 
        break; 
       } 

      } 
     } 
    } 
} 

return sameBooks; 


} 
+1

Beachten Sie, dass, obwohl dies die Warnung behebt, der Code immer noch fehlerhaft ist: if personA.size()> = personB.size(), it gibt eine leere Liste von Büchern zurück ... – tucuxi

+0

Vielen Dank, ich schätze Ihre Hilfe. –

0

Return-Typ Ihrer Methode ist ArrayList. Sie haben return-Anweisung in verschiedenen bedingten Blöcken hinzugefügt, aber Sie haben keine return-Anweisung außerhalb aller bedingten Blöcke unmittelbar vor der schließenden Klammer Ihrer commonBooks-Methode hinzugefügt.

Sie müssen ArrayList außerhalb aller else oder if Blöcke kurz vor der schließenden Klammer Ihrer Methode zurückgeben.

else { 
     return sameBooks; 
} 

    //add return statement here  

} //closing parenthesis of commonBooks method 
0

Sie überschätzen dies!

Angenommen, Sie haben eine Sammlung [a, b, c] und eine andere Sammlung [b, c, d].

Sie müssen nur über eine Sammlung iterieren und sie mit der anderen vergleichen. zB:

is 'a' in [b, c, d] ? no don't add a 
is 'b' in [b, c, d] ? yes add b 
is 'c' in [b, c, d] ? yes add c 
Result: [b, c] 

Beachten Sie, dass Sie den zweiten Satz nicht überlappen mussten? Sie haben nie d ausgewertet, aber Sie wissen bereits, dass es nicht in der ersten Liste ist. Du hast jedes Element in der ersten Liste bereits überprüft, also gibt es keine Möglichkeit, dass 'd' mit [a, b, c] übereinstimmt.

for (int i = 0; i < personA.size(); i++) { 
    Book ndx = personA.get(i); 
    if (personB.contains(ndx)) { 
     sameBooks.add(ndx); 
    } 
} 
return sameBooks; 
0

siehe Java Compare Two Lists

Sie intersection() und subtract() Methoden aus CollectionUtils versuchen.

Die intersection() -Methode gibt Ihnen eine Sammlung mit gemeinsamen Elementen und die subtract() -Methode gibt Ihnen alle ungewöhnlichen.

Sie sollten auch um ähnliche Elemente nehmen

Ich glaube, Ihr Buch Klasse Comparator Schnittstelle implementieren sollten, so dass Sie diese richtig nutzen können.

+1

Es ist einfacher, Sets und 'retainAll' zu verwenden - keine externen Abhängigkeiten erforderlich. Sie beantworten auch nicht die ursprüngliche OP-Frage, "was ist falsch in meinem Code" – tucuxi

1

Wenn Ihre Methode deklariert, dass ein ArrayList zurückgegeben wird, müssen alle möglichen Pfade durch Ihren Code eine ArrayList zurückgeben.VHS answer weist richtig auf eine Behebung hin: Ausfahrt an nur einer Stelle, die eine ArrayList zurückgibt, und dass alle Pfade durchlaufen müssen.

Eine andere Lösung, die über Ihre ursprüngliche Frage geht, ist einfacher Code zu verwenden:

HashSet<Book> readByA = new HashSet<>(a.getRead()); 
readByA.retainAll(b.getRead()); // remove all books that b has not read 
return new ArrayList<>(readByA); 

Mit HashSet s Sie haben implementiert erfordert equals() und hashCode() Methoden in Ihrer Klasse Book, though. Viele IDEs bieten an, sie für Sie zu implementieren. Auf der anderen Seite ist dies für eine große Anzahl von Büchern viel, viel schneller als Ihr aktueller Code.


Der ursprüngliche Code hat auch mindestens einen großen Fehler, da es eine leere Liste, wenn personA.size() >= personB.size() zurückgibt. Zum Beispiel gibt es bei zwei identischen Listen derzeit keine Bücher, die beiden gemeinsam sind!

es wieder Umschreiben, diesmal ohne Sätze:

ArrayList<Book> readByB = b.getRead(); 
ArrayList<Book> sameBooks = new ArrayList<Book>(); 
for (Book b : a.getRead()) { 
    if (readByB.contains(b)) sameBooks.add(b); 
} 
return sameBooks; 

Beachten Sie, dass alle Dinge gleich sind, kürzerer Code ist leichter zu als längere Codefragmente zu lesen und zu verstehen. Das ist ein Grund zu bevorzugen ...

for (Book b : a.getRead()) { 

... bis ...

ArrayList<Book> readByA = a.getRead(); 
// ... 
for (int i = 0; i < readByA.size(); i++) { 
    Book b = readByA.get(i); 

... Sie sparen 2 Zeilen (66%!) Und sind nicht mehr verwirrt von 2 Hilfsvariablen, i und readByA, die nicht mehr wirklich benötigt werden.

+0

Danke, aber das ist ein bisschen zu weit für mein Projekt. –

+0

Ich habe etwas mehr Code hinzugefügt, diesmal ohne Sets zu verwenden. Beachten Sie, dass Ihr aktueller Code, selbst wenn VHS repariert wird, zu komplex ist und für viele Eingaben falsche Ergebnisse liefert. – tucuxi

0

Hier ist eine Java-8-Streaming-Lösung:

import java.util.List; 
import java.util.stream.Collectors; 

class Class { 
    public static List<Book> commonBooks(Person a, Person b) { 
    List<Book> personA = a.getRead(); 
    List<Book> personB = b.getRead(); 
    return personA.stream() 
     .filter(personB::contains) 
     .collect(Collectors.toList()); 
    } 
} 
+0

OP kann bereits angenommen werden, dass ein Working-Equalizer vorhanden ist (andernfalls würde contains() fehlschlagen). – tucuxi

+0

Großartig, ich werde das aus der Antwort herausschneiden. – Andreas