Ich muss die Anzahl der Elemente in einem Iterable
in Java herausfinden . Ich weiß, ich kann dies tun:
Iterable values = ...
it = values.iterator();
while (it.hasNext()) {
it.next();
sum++;
}
Ich könnte auch so etwas machen, weil ich die Objekte im Iterable nicht mehr brauche:
it = values.iterator();
while (it.hasNext()) {
it.remove();
sum++;
}
Ein kleiner Benchmark zeigte keinen großen Leistungsunterschied, keine Kommentare oder andere Ideen für dieses Problem?
remove()
ohnenext()
vorher anzurufen .Antworten:
TL; DR: Verwenden Sie die Utility-Methode
Iterables.size(Iterable)
der großen Guava- Bibliothek.Von Ihren beiden Codefragmenten sollten Sie das erste verwenden, da das zweite alle Elemente entfernt
values
, sodass es danach leer ist. Das Ändern einer Datenstruktur für eine einfache Abfrage wie ihre Größe ist sehr unerwartet.Die Leistung hängt von Ihrer Datenstruktur ab. Wenn es sich zum Beispiel tatsächlich um ein
ArrayList
Element handelt, ist das Entfernen von Elementen von Anfang an (was Ihre zweite Methode tut) sehr langsam (die Berechnung der Größe wird zu O (n * n) anstelle von O (n), wie es sein sollte).Wenn die Möglichkeit besteht, dass
values
es sich tatsächlich um eineCollection
und nicht nur um eine handeltIterable
, überprüfen Sie dies im Allgemeinen und rufen Siesize()
an, falls:Der Aufruf
size()
wird in der Regel viel schneller sein als die Anzahl der Elemente zu zählen, und dieser Trick ist genau das, wasIterables.size(Iterable)
von Guava für Sie tut.quelle
values
Wenn Sie mit Java 8 arbeiten, können Sie Folgendes verwenden:
Dies funktioniert nur, wenn die iterierbare Quelle eine bestimmte Größe hat. Die meisten Spliteratoren für Sammlungen werden, aber Sie können Probleme haben, wenn es von einem
HashSet
oderResultSet
zum Beispiel kommt.Sie können den Javadoc hier überprüfen .
Wenn Java 8 keine Option ist oder Sie nicht wissen, woher das iterable stammt, können Sie den gleichen Ansatz wie Guave verwenden:
quelle
Dies ist vielleicht etwas spät, kann aber jemandem helfen. Ich stoße auf ein ähnliches Problem
Iterable
in meiner Codebasis und die Lösung bestand darin,for each
ohne expliziten Aufruf zu verwendenvalues.iterator();
.quelle
Sie können Ihre Iterable in eine Liste umwandeln und dann .size () darauf verwenden.
Aus Gründen der Klarheit erfordert die obige Methode den folgenden Import:
quelle
Genau genommen hat Iterable keine Größe. Stellen Sie sich die Datenstruktur wie einen Zyklus vor.
Und denken Sie an die folgende Iterable-Instanz: Keine Größe:
quelle
Ich würde mich für
it.next()
den einfachen Grund entscheiden, dernext()
garantiert implementiert wird, währendremove()
es sich um eine optionale Operation handelt.quelle
remove
wurde bereits als die falsche Methode zum Zählen von Elementen von a bezeichnet.Iterator
Es spielt also keine Rolle, ob das, was wir nicht tun werden, implementiert ist oder nicht.remove
wird implementiert, warum wäre es falsch, es zu benutzen? Übrigens werden Abstimmungen normalerweise für falsche Antworten oder Antworten verwendet, die schlechte Ratschläge geben. Ich kann nicht sehen, wie sich diese Antwort für irgendetwas davon qualifiziert.Java 8 und höher
quelle
Für mich sind dies nur verschiedene Methoden. Der erste lässt das Objekt, auf dem Sie iterieren, unverändert, während der zweite es leer lässt. Die Frage ist, was Sie tun möchten. Die Komplexität des Entfernens basiert auf der Implementierung Ihres iterierbaren Objekts. Wenn Sie Sammlungen verwenden - erhalten Sie einfach die Größe, wie sie von Kazekage Gaara vorgeschlagen wurde -, ist dies normalerweise der beste Ansatz in Bezug auf die Leistung.
quelle
Warum verwenden Sie nicht einfach die
size()
Methode auf IhremCollection
, um die Anzahl der Elemente zu ermitteln?Iterator
soll nur iterieren, sonst nichts.quelle
Iterator
undIterable
. Siehe die abgestimmte Antwort für den richtigen Weg.Anstatt Schleifen zu verwenden und jedes Element zu zählen oder eine Bibliothek eines Drittanbieters zu verwenden, können wir die Iterable einfach in ArrayList typisieren und ihre Größe ermitteln.
quelle