Ich habe ein Array von Grundelementen, zum Beispiel für int, int [] foo. Es könnte klein sein oder nicht.
int foo[] = {1,2,3,4,5,6,7,8,9,0};
Was ist der beste Weg, um daraus ein zu erstellen Iterable<Integer>
?
Iterable<Integer> fooBar = convert(foo);
Anmerkungen:
Bitte antworten Sie nicht mit Schleifen (es sei denn, Sie können eine gute Erklärung geben, wie der Compiler etwas Kluges dagegen unternimmt?)
Beachten Sie auch das
int a[] = {1,2,3};
List<Integer> l = Arrays.asList(a);
Wird nicht einmal kompilieren
Type mismatch: cannot convert from List<int[]> to List<Integer>
Aktivieren Sie auch Warum kann ein Array nicht Iterable zugewiesen werden? vor der Antwort.
Wenn Sie eine Bibliothek (z. B. Guave) verwenden, erklären Sie bitte, warum dies die beste ist. (Weil es von Google keine vollständige Antwort ist: P)
Zuletzt, da es eine Hausaufgabe zu geben scheint, vermeiden Sie es, Hausaufgabencode zu veröffentlichen.
Antworten:
Sie müssen jedoch ein
Integer
Array (keinint
Array) verwenden, damit dies funktioniert.Für Grundelemente können Sie Guave verwenden:
Für Java8: (aus Jin Kwons Antwort)
quelle
int
, nichtInteger
2)List
ist schonIterable
so ist die dritte Zeile sinnlos.nur meine 2 Cent:
quelle
Iterator<Character>
aus einem zu erstellenString
. Das Implementieren eigenerIterator
Werte scheint der einzige Weg zu sein, um zu vermeiden, dass unnötig alle Werte durchlaufen werden, um vom Objekttyp in den primitiven Typ zu konvertieren (Ints.asList()
z. B. über Guavas ), nur um einenIterator
von demList
erstellten zu erhalten.Mit Java 8 können Sie dies tun.
quelle
Guava stellt den gewünschten Adapter als Int.asList () bereit . Für jeden primitiven Typ in der zugehörigen Klasse gibt es ein Äquivalent, z. B.
Booleans
fürboolean
usw.Die oben genannten Vorschläge
Arrays.asList
funktionieren nicht, auch wenn sie kompiliert werden, weil SieIterator<int[]>
eher eine als erhaltenIterator<Integer>
. Anstatt eine von Ihrem Array unterstützte Liste zu erstellen, haben Sie eine 1-Element-Liste von Arrays erstellt, die Ihr Array enthält.quelle
Ich hatte das gleiche Problem und löste es so:
Der Iterator selbst ist faul,
UnmodifiableIterator
aber genau das habe ich gebraucht.quelle
In Java 8 oder höher
Iterable
wird eine funktionale Schnittstelle zurückgegebenIterator
. Also kannst du das machen.quelle
Zunächst kann ich nur zustimmen, dass dies
Arrays.asList(T...)
eindeutig die beste Lösung für Wrapper-Typen oder Arrays mit nicht primitiven Datentypen ist. Diese Methode ruft einen Konstruktor einer einfachen privaten statischenAbstractList
Implementierung in derArrays
Klasse auf, der im Grunde die angegebene Array-Referenz als Feld speichert und eine Liste simuliert, indem die erforderlichen Methoden überschrieben werden.Wenn Sie für Ihr Array zwischen einem primitiven Typ oder einem Wrapper-Typ wählen können, würde ich den Wrapper-Typ für solche Situationen verwenden, aber natürlich ist er nicht immer nützlich oder erforderlich. Es gibt nur zwei Möglichkeiten:
1) Sie können eine Klasse mit einer statischen Methode für jedes primitive Datentyp-Array erstellen (
boolean, byte, short, int, long, char, float, double
Rückgabe einesIterable<
WrapperType>
. Diese Methoden würden anonyme Klassen vonIterator
(außerdem) verwendenIterable
), die die Referenz des Arguments der umfassenden Methode (zum Beispiel anint[]
) als Feld enthalten dürfen, um die Methoden zu implementieren.-> Dieser Ansatz ist performant und spart Ihnen Speicherplatz (mit Ausnahme des Speichers der neu erstellten Methoden, obwohl die Verwendung
Arrays.asList()
auf die gleiche Weise Speicherplatz beanspruchen würde).2) Da Arrays keine Methoden haben (um auf der Seite gelesen zu werden) Sie haben keine
Iterator
Instanz bereitgestellt. Wenn Sie wirklich zu faul sind, um neue Klassen zu schreiben, müssen Sie eine Instanz einer bereits vorhandenen Klasse verwenden, die implementiert wird,Iterable
da es keinen anderen Weg gibt als das InstanziierenIterable
oder einen Subtyp.Der EINZIGE Weg, um eine vorhandene Implementierung eines Sammlungsderivats zu erstellen
Iterable
Verwenden Sie eine Schleife (außer Sie verwenden anonyme Klassen wie oben beschrieben) oder instanziieren Sie eineIterable
implementierende Klasse, deren Konstruktor ein primitives Typarray zulässt (daObject[]
Arrays mit primitiven Tybelementen nicht zulässig sind), aber meines Wissens die Java-API gibt es keine solche Klasse.Der Grund für die Schleife kann leicht erklärt werden:
Für jede Sammlung benötigen Sie Objekte, und primitive Datentypen sind keine Objekte. Objekte sind viel größer als primitive Typen, sodass zusätzliche Daten erforderlich sind, die für jedes Element des primitiven Typarrays generiert werden müssen. Das heißt, wenn zwei Dreierarten (Verwenden
Arrays.asList(T...)
oder Verwenden einer vorhandenen Sammlung) ein Aggregat von Objekten erfordern, müssen Sie für jeden primitiven Wert von Ihren erstellenint[]
Array das Wrapper-Objekt. Der dritte Weg würde das Array so wie es ist verwenden und es in einer anonymen Klasse verwenden, da ich denke, dass es aufgrund der schnellen Leistung vorzuziehen ist.Es gibt auch eine dritte Strategie, bei der ein
Object
as-Argument für die Methode verwendet wird, bei der Sie das Array verwenden möchten, oderIterable
bei der Typprüfungen erforderlich sind, um herauszufinden, welchen Typ das Argument hat. Ich würde es jedoch überhaupt nicht empfehlen, wie Sie es normalerweise benötigen Beachten Sie, dass das Objekt nicht immer den erforderlichen Typ hat und dass Sie in bestimmten Fällen separaten Code benötigen.Zusammenfassend ist es die Schuld von Javas problematischem Generic Type-System, das es nicht erlaubt, primitive Typen als generischen Typ zu verwenden, der durch einfache Verwendung viel Code sparen würde
Arrays.asList(T...)
. Sie müssen also für jedes primitive Typarray eine solche Methode programmieren (die im Grunde genommen keinen Unterschied zum von einem C ++ - Programm verwendeten Speicher macht, der für jedes verwendete Typargument eine separate Methode erstellen würde.quelle
Sie können
IterableOf
von Cactoos verwenden :Dann können Sie daraus eine Liste machen, indem Sie
ListOf
:Oder einfach das:
quelle
Obwohl eine ähnliche Antwort bereits veröffentlicht wurde, war der Grund für die Verwendung des neuen PrimitiveIterator.OfInt meines Erachtens nicht klar. Eine gute Lösung ist die Verwendung von Java 8 PrimitiveIterator, da es auf primitive int-Typen spezialisiert ist (und die zusätzliche Strafe für das Ein- und Auspacken vermeidet):
Ref: https://doc.bccnsoft.com/docs/jdk8u12-docs/api/java/util/PrimitiveIterator.OfInt.html
quelle
In Java8 kann der IntSteam-Stream in einen Stream mit Ganzzahlen umgewandelt werden.
Ich denke, die Leistung hängt von der Größe des Arrays ab.
quelle