Wann sollte ich einen Parameter von Iterable akzeptieren vs. Sammlung auf Java?

Lesezeit: 5 Minuten

Benutzer-Avatar
Daniel Fortunov

Was sind die Überlegungen zur Verwendung Iterable<T> vs. Collection<T> auf Java?

Ziehen Sie beispielsweise in Betracht, einen Typ zu implementieren, der hauptsächlich damit befasst ist, eine Auflistung von zu enthalten Foos und einige zugehörige Metadaten. Der Konstruktor dieses Typs erlaubt die einmalige Initialisierung der Objektliste. (Die Metadaten können später festgelegt werden.) Welchen Typ sollte dieser Konstruktor akzeptieren? Iterable<Foo>oder Collection<Foo>?

Was sind die Überlegungen für diese Entscheidung?

Nach dem Muster, das von Bibliothekstypen wie z ArrayList (die von jedem initialisiert werden kann Collectionaber nicht ein Iterable) würde mich dazu bringen, zu verwenden Collection<Foo>.

Aber warum nicht akzeptieren Iterable<Foo>, da dies für die Initialisierungsanforderungen ausreicht? Warum ein höheres Maß an Funktionalität verlangen (Collection) vom Verbraucher, als unbedingt erforderlich (Iterable)?

Benutzer-Avatar
Jon Skeet

Viele der Sammlungstypen existierten schon vorher Iterable<T> (das erst in 1.5 eingeführt wurde) – es gab wenig Grund, einen Konstruktor hinzuzufügen, der akzeptiert werden sollte Iterable<T> ebenso gut wie Collection<T> aber das Ändern des vorhandenen Konstruktors wäre eine Breaking Change gewesen.

Ich persönlich würde verwenden Iterable<T> wenn Sie damit alles tun können, was Sie wollen. Es ist flexibler für Anrufer und vor allem lässt es Sie tun verhältnismäßig Einfache Filterung/Projektion/usw. mit den Google Java Collections (und zweifellos ähnlichen Bibliotheken).

  • Sie sagen, es wäre eine “Breaking Change”. Was würde kaputt gehen, wenn (sagen wir) der Konstruktorparameter ArrayList von Collection in Iterable geändert würde?

    – finnw

    25. August 2009 um 12:54 Uhr

  • @finnw: Es wäre quellkompatibel, aber nicht binärkompatibel: Bestehende (kompilierte) Klassen, die den aktuellen Konstruktor verwenden, würden brechen (da sie den Collection-Param-Konstruktor explizit aufrufen) und müssen neu kompiliert werden.

    – Paulo Ebermann

    7. März 2011 um 22:10 Uhr

Ein Iterable produziert Iterator Objekte. Ein Iterator Objekt, per Definition, iteriert. Beachten Sie, dass die Iterator Schnittstelle macht keine Zusage, wie oft next() kann vorher angerufen werden hasNext() kehrt zurück false. Ein Iterator könnte möglicherweise iterieren Integer.MAX_VALUE + 1 Werte vor seinen hasNext() Methode zurück false.

Allerdings, ein Collection ist eine Sonderform von Iterable. Weil ein Collection kann nicht mehr haben als Integer.MAX_VALUE Elemente (aufgrund der size() Methode), wird natürlich davon ausgegangen, dass seine Iterator Objekte werden nicht über so viele Elemente iterieren.

Durch die Annahme von a Collection eher als ein Iterablekann Ihre Klasse eine gewisse Garantie dafür haben, wie viele Elemente übergeben werden. Dies ist besonders wünschenswert, wenn Ihre Klasse selbst eine ist Collection.

Nur meine zwei Cent…

  • Das verbietet sich ziemlich unvernünftig Iterables auf Kosten der Nicht-Erfassung, völlig vernünftiger Iterables.

    – Jon Skeet

    21. Juli 2009 um 15:32 Uhr

  • Und tatsächlich ein Collection kann auch größer als Integer.MAX_VALUE sein, dann gibt die Größenmethode nur Integer.MAX_VALUE zurück. Der Vorteil einer Collection ist meistens die size() -Methode (alles andere kann zusätzlich zu Iterator und size implementiert werden, wie AbstractCollection zeigt), verwenden Sie also eine Collection wenn Sie die Größe vor dem Iterieren benötigennicht wenn Sie nur iterieren möchten.

    – Paulo Ebermann

    7. März 2011 um 22:15 Uhr

  • @Paŭlo: Wow, das wusste ich nicht Collection.size() kehrt zurück Integer.MAX_VALUE wenn es mehr als so viele Elemente enthält!

    – Adam Paynter

    8. März 2011 um 0:07 Uhr

  • Jawohl! Javadoc-Beweis!

    – Yinkrash

    30. November 2011 um 7:29 Uhr

Benutzer von Spring Data JPA werde feststellen, dass die Repositories Sammlungen des Typs zurückgeben Iterable<T>.

Bei Projekten, an denen ich in der Vergangenheit gearbeitet habe, die verwenden Springhabe ich festgestellt, dass die Notwendigkeit, eine Sammlung nach dem Abrufen zu bearbeiten, dies oft diktiert hat Iterable<T> in der Business-Schicht verwendet wird, anstatt Collection<T> um ein Objekt auszuwählen T aus der Sammlung.

Alle Sammlungen sind Iterable (das sind die Schnittstellen, die die erweitern Collection Schnittstelle, also nicht Map!), also mit Iterable in der Business-Schicht ist lediglich ein Fall, in dem auf eine Sammlung durch ihren Supertyp verwiesen wird, und erlaubt dennoch die Verwendung von for-each zu iterieren.

Wenn Sie den Inhalt einer Sammlung bearbeiten müssen, können Sie mit einer bequemen Methode eine neue füllen Collectiondamit Sie es nutzen können contains(), remove()etc mit den ursprünglichen Sammlungsdaten.

Alternativ werden zu diesem Zweck praktische Methoden von gängigen APIs von Drittanbietern wie Google Guava und Apache Commons bereitgestellt.

Verwenden Sie die allgemeinste Schnittstelle, die Sie können. Da Sie nur iterieren werden, würde ich sagen Iterable ist der richtige Weg (da es faule Iteratoren usw. zulässt). Es ist Ihnen egal, woher der Iterator kommt, also beschränken Sie ihn nicht mehr als nötig.

Einige Konstruktoren, z. B. ArrayList(Collection c), verwenden aus Effizienzgründen die Methode toArray() von Collection.

Benutzer-Avatar
Rick

Siehe „Warum wird so viel Wert auf Iteratoren und Iterables gelegt?“ auf der Häufig gestellte Fragen zur Google-Sammlung
für ein anständiges Argument für die Bevorzugung von Iteratoren, insbesondere wenn es um viele Daten geht. Eine Analogie, die hilfreich sein könnte, besteht darin, den Unterschied zwischen Vorwärts-Nur-Lese-Cursoren und scrollbaren Cursorn zu betrachten.

Benutzer-Avatar
Patrik McDonald

Wenn Sie sich für Collection entscheiden, kann Ihre Klasse nur von einer Collection initialisiert werden, wenn Sie sich für Iterable entscheiden, können Sie entweder von Collection oder iterable initialisieren.

Da der Aufwand und die Leistung für beide gleich sein werden, ist es absolut sinnvoll, Iterable im Konstruktor zu akzeptieren.

1228420cookie-checkWann sollte ich einen Parameter von Iterable akzeptieren vs. Sammlung auf Java?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy