Wie konvertiere ich eine ArrayList, die Ganzzahlen enthält, in ein primitives int-Array?

297

Ich versuche, eine ArrayList, die Integer-Objekte enthält, mit dem folgenden Code in primitive int [] zu konvertieren, aber es wird ein Fehler bei der Kompilierung ausgelöst. Ist es möglich in Java zu konvertieren?

List<Integer> x =  new ArrayList<Integer>();
int[] n = (int[])x.toArray(int[x.size()]);
Snehal
quelle
10
Kein genaues Duplikat dieser Frage (obwohl auch nicht sehr weit)
Jonik
1
Ja, dies ist eine ArrayList. "Duplikat" handelt von einem normalen Array.
Scott McIntyre
3
Wenn Sie keine primitiven Ints benötigen, können Sie Folgendes verwenden: List<Integer> x = new ArrayList<Integer>(); Integer[] n = x.toArray(new Integer[0]);
Evorlor

Antworten:

219

Sie können konvertieren, aber ich glaube nicht, dass etwas eingebaut ist, um dies automatisch zu tun:

public static int[] convertIntegers(List<Integer> integers)
{
    int[] ret = new int[integers.size()];
    for (int i=0; i < ret.length; i++)
    {
        ret[i] = integers.get(i).intValue();
    }
    return ret;
}

(Beachten Sie, dass dies eine NullPointerException auslöst, wenn eines integersoder mehrere Elemente darin enthalten sind null.)

BEARBEITEN: Gemäß den Kommentaren möchten Sie möglicherweise den Listeniterator verwenden, um unangenehme Kosten mit Listen wie den folgenden zu vermeiden LinkedList:

public static int[] convertIntegers(List<Integer> integers)
{
    int[] ret = new int[integers.size()];
    Iterator<Integer> iterator = integers.iterator();
    for (int i = 0; i < ret.length; i++)
    {
        ret[i] = iterator.next().intValue();
    }
    return ret;
}
Jon Skeet
quelle
21
Es ist möglicherweise besser, mit dem Iterator der Liste (jeweils für) zu iterieren, um Leistungseinbußen bei Listen zu vermeiden, deren Zugriff nicht O (1) ist.
Matthew Willis
@ Matthew: Ja, möglicherweise - wird bearbeitet, um das als Alternative zu geben.
Jon Skeet
1
Sie können auch die Tatsache nutzen, dass die ArrayList Iterable (über die Collection-Vererbung) implementiert und Folgendes tut: for (int n: integer) {ret [counter ++] = n; } ... und initialisiere int counter = 0;
Gardarh
8
viel einfacher jetzt in Java8:integers.stream().mapToInt(Integer::valueOf).toArray
Manish Patel
241

Wenn Sie verwenden Es gibt auch einen anderen Weg, dies zu tun.

int[] arr = list.stream().mapToInt(i -> i).toArray();

Was es tut ist:

  • ein Stream<Integer>von der Liste bekommen
  • Erhalten eines IntStreamdurch Zuordnen jedes Elements zu sich selbst (Identitätsfunktion), Entpacken des intvon jedem IntegerObjekt gehaltenen Werts (automatisch seit Java 5 durchgeführt)
  • Abrufen des Arrays intdurch AufrufentoArray

Sie können auch explizit intValueüber eine Methodenreferenz aufrufen , dh:

int[] arr = list.stream().mapToInt(Integer::intValue).toArray();

Es ist auch erwähnenswert, dass Sie eine erhalten könnten, NullPointerExceptionwenn Sie eine nullReferenz in der Liste haben. Dies könnte leicht vermieden werden, indem der Stream-Pipeline eine Filterbedingung wie folgt hinzugefügt wird:

                       //.filter(Objects::nonNull) also works
int[] arr = list.stream().filter(i -> i != null).mapToInt(i -> i).toArray();

Beispiel:

List<Integer> list = Arrays.asList(1, 2, 3, 4);
int[] arr = list.stream().mapToInt(i -> i).toArray(); //[1, 2, 3, 4]

list.set(1, null); //[1, null, 3, 4]
arr = list.stream().filter(i -> i != null).mapToInt(i -> i).toArray(); //[1, 3, 4]
Alexis C.
quelle
Ich sehe, dass dies für doubleTypen verwendet werden kann; Gibt es kein Äquivalent für floatTypen?
code_dredd
Sie haben den Vorteil von Java 8 durch Ihre ausführliche Erklärung gesehen.
Eugene
Und deshalb ist die Java 8+ Stream API wunderschön.
Pranav A.
67

Google Guava

Google Guava bietet eine gute Möglichkeit, dies durch einen Anruf zu tun Ints.toArray.

List<Integer> list = ...;
int[] values = Ints.toArray(list);
Snehal
quelle
6
Ich denke, das wird die Antwort für mich sein - ich werde jeden Tag eine Bibliothek über eine Copy-Paste-Funktion übernehmen. Insbesondere eine Bibliothek, die ein Projekt mit anständiger Größe wahrscheinlich bereits verwendet. Ich hoffe, dass diese Antwort in Zukunft mehr Stimmen und Sichtbarkeit erhält.
Sean Connolly
61

Apache Commons verfügt über eine ArrayUtils-Klasse mit einer Methode toPrimitive (), die genau dies tut.

import org.apache.commons.lang.ArrayUtils;
...
    List<Integer> list = new ArrayList<Integer>();
    list.add(new Integer(1));
    list.add(new Integer(2));
    int[] intArray = ArrayUtils.toPrimitive(list.toArray(new Integer[0]));

Wie Jon gezeigt hat, ist es jedoch ziemlich einfach, dies selbst zu tun, anstatt externe Bibliotheken zu verwenden.

Björn
quelle
2
Beachten Sie, dass bei diesem Ansatz zwei vollständige Kopien der Sequenz erstellt werden: eine von toArray erstellte Ganzzahl [] und eine in toPrimitive erstellte int []. Die andere Antwort von Jon erstellt und füllt nur ein Array. Wenn Sie große Listen haben und die Leistung wichtig ist, sollten Sie dies berücksichtigen.
Paraquat
Ich habe die Leistung mit ArrayUtils im Vergleich zu reinem Java gemessen und auf kleinen Listen (<25 Elemente) ist reines Java mehr als 100-mal schneller. Für 3k-Elemente ist reines Java immer noch fast zweimal schneller ... (ArrayList <Integer> -> int [])
Oskar Lund
@paraquat & Oskar Lund das ist eigentlich nicht richtig. Ja, der bereitgestellte Code erstellt zwei Arrays, dieser Ansatz jedoch nicht. Das Problem in diesem Code ist hier die Verwendung eines Arrays mit der Länge Null als Argument. Der Quellcode ArrayList.toArray zeigt, dass das ursprüngliche Array verwendet wird, wenn der Inhalt passt. Ich denke, in einem fairen Vergleich werden Sie feststellen, dass diese Methode genauso effizient ist (wenn nicht sogar mehr) und natürlich weniger Code zu warten ist.
Sean Connolly
1
Was ist der Zweck der neuen Ganzzahl [0]?
Adam Hughes
41

Ich halte das Iterieren mit dem Iterator der Liste für eine bessere Idee, da list.get(i)die Leistung je nach Implementierung der Liste schlecht sein kann:

private int[] buildIntArray(List<Integer> integers) {
    int[] ints = new int[integers.size()];
    int i = 0;
    for (Integer n : integers) {
        ints[i++] = n;
    }
    return ints;
}
Matthew Willis
quelle
6

Die Verwendung von Dollar sollte recht einfach sein:

List<Integer> list = $(5).toList(); // the list 0, 1, 2, 3, 4  
int[] array = $($(list).toArray()).toIntArray();

Ich plane , die DSL zu verbessern , um das Zwischenprodukt zu entfernen toArray()Anruf

dfa
quelle
1
Hey, ich wollte nur sagen, dass ich Dollar noch nie gesehen habe, aber ich probiere es definitiv bei meinem nächsten Projekt aus. Das ist eine nette kleine API, die Sie dort haben, machen Sie weiter so :)
Bart Vandendriessche
4

Das funktioniert gut für mich :)

Gefunden unter https://www.techiedelight.com/convert-list-integer-array-int/

import java.util.Arrays;
import java.util.List;

class ListUtil
{
    // Program to convert list of integer to array of int in Java
    public static void main(String args[])
    {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

        int[] primitive = list.stream()
                            .mapToInt(Integer::intValue)
                            .toArray();

        System.out.println(Arrays.toString(primitive));
    }
}
Angelhernandez
quelle
3

Es verwirrt mich, dass wir einmalige benutzerdefinierte Methoden empfehlen, wenn eine einwandfreie, gut genutzte Bibliothek wie Apache Commons das Problem bereits gelöst hat. Obwohl die Lösung trivial, wenn nicht absurd ist, ist es unverantwortlich, ein solches Verhalten aufgrund langfristiger Wartung und Zugänglichkeit zu fördern.

Gehen Sie einfach mit Apache Commons

Andrew F.
quelle
7
Ich stimme dem vorherigen Kommentator zu. Sie ziehen nicht nur Apache Commons ein, sondern es wird auch leicht zu einer großen Anzahl von transitiven Abhängigkeiten übersetzt, die ebenfalls hineingezogen werden müssen. Vor kurzem konnte ich eine erstaunliche Anzahl von Abhängigkeiten entfernen, indem ich eine Codezeile ersetzte :-( Abhängigkeiten sind kostspielig und Grundcode wie diesen zu schreiben ist eine gute Praxis
Peter Kriens
1
Einverstanden mit @PeterKriens. Wenn überhaupt, liegt der Fehler in Java daran, dass einfache Konvertierungen wie diese in ihren Standarddatentypen nicht unterstützt werden
Adam Hughes
3

Wenn Sie Eclipse-Sammlungen verwenden , können Sie mit dieser collectInt()Methode von einem Objektcontainer zu einem primitiven int-Container wechseln.

List<Integer> integers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
MutableIntList intList =
  ListAdapter.adapt(integers).collectInt(i -> i);
Assert.assertArrayEquals(new int[]{1, 2, 3, 4, 5}, intList.toArray());

Wenn Sie Ihre ArrayListin a konvertieren können FastList, können Sie den Adapter entfernen.

Assert.assertArrayEquals(
  new int[]{1, 2, 3, 4, 5},
  Lists.mutable.with(1, 2, 3, 4, 5)
    .collectInt(i -> i).toArray());

Hinweis: Ich bin ein Committer für Eclipse-Sammlungen.

Craig P. Motlin
quelle
3

Java 8:

int[] intArr = Arrays.stream(integerList).mapToInt(i->i).toArray();
EssaidiM
quelle
2

Arrays.setAll ()

    List<Integer> x = new ArrayList<>(Arrays.asList(7, 9, 13));
    int[] n = new int[x.size()];
    Arrays.setAll(n, x::get);

    System.out.println("Array of primitive ints: " + Arrays.toString(n));

Ausgabe:

Array primitiver Ints: [7, 9, 13]

Das gleiche funktioniert für eine Reihe longoder double, aber nicht für Arrays von boolean, char, byte, shortoder float. Wenn Sie eine wirklich große Liste haben, gibt es sogar eine parallelSetAllMethode, die Sie stattdessen verwenden können.

Für mich ist das gut und elegant genug, dass ich weder eine externe Bibliothek erhalten noch Streams dafür verwenden möchte.

Dokumentationslink: Arrays.setAll(int[], IntUnaryOperator)

Ole VV
quelle
1

Sie können es einfach in ein Array kopieren:

int[] arr = new int[list.size()];
for(int i = 0; i < list.size(); i++) {
    arr[i] = list.get(i);
}

Nicht zu schick; aber hey, es funktioniert ...

sagiksp
quelle
1

Eine sehr einfache einzeilige Lösung ist:

Integer[] i = arrlist.stream().toArray(Integer[]::new);
PramodG
quelle
0

Dieses Codesegment funktioniert für mich. Versuchen Sie Folgendes:

Integer[] arr = x.toArray(new Integer[x.size()]);

Erwähnenswert ist, dass ArrayList folgendermaßen deklariert werden sollte:

ArrayList<Integer> list = new ArrayList<>();
user3444748
quelle
5
Hallo, nur eine sanfte Erinnerung daran, dass OP ein primitives Array und kein Objekt-Array haben möchte.
OLIVER.KOO
3
Primitive int not wrapper Integer!
Bartzilla
-4
   List<Integer> list = new ArrayList<Integer>();

    list.add(1);
    list.add(2);

    int[] result = null;
    StringBuffer strBuffer = new StringBuffer();
    for (Object o : list) {
        strBuffer.append(o);
        result = new int[] { Integer.parseInt(strBuffer.toString()) };
        for (Integer i : result) {
            System.out.println(i);
        }
        strBuffer.delete(0, strBuffer.length());
    }
CodeMadness
quelle
1
Diese Antwort funktioniert nicht, sondern gibt ein Array mit einem einzelnen Element anstelle mehrerer Elemente zurück.
Mysticial
Warum einen StringBuffer verwenden? Warum die Ganzzahl in einen String und dann in eine Ganzzahl und dann in eine int und dann wieder in eine Ganzzahl konvertieren? Warum ein Array mit einem einzelnen Element verwenden und warum dieses Array mit einem einzelnen Element durchlaufen, wenn es nur ein Element enthält? Warum die Ganzzahlen in Objekte in der äußeren Schleife umwandeln? Hier gibt es so viele Fragen. Ist @CodeMadness nur ein Trollkonto?
Victor Zamanian
-5
Integer[] arr = (Integer[]) x.toArray(new Integer[x.size()]);

Zugang arrwie gewohnt int[].

snn
quelle
5
Dies beantwortet nicht die Frage, die Frage war über die Konvertierung in primitiven Typ (int)
Asaf