Dies ähnelt dieser Frage: Wie konvertiere ich int [] in Integer [] in Java?
Ich bin neu in Java. Wie kann ich einen List<Integer>
in int[]
in Java konvertieren? Ich bin verwirrt, weil List.toArray()
tatsächlich einen Object[]
zurückgibt, der in einen Integer[]
oder int[]
umgewandelt werden kann.
Im Moment benutze ich dazu eine Schleife:
int[] toIntArray(List<Integer> list){
int[] ret = new int[list.size()];
for(int i = 0;i < ret.length;i++)
ret[i] = list.get(i);
return ret;
}
Ich bin sicher, es gibt einen besseren Weg, dies zu tun.
Leider glaube ich nicht, dass es wirklich eine bessere Möglichkeit gibt, dies zu tun, da Java primitive Typen, Boxen, Arrays und Generika behandelt. Speziell:
List<T>.toArray
funktioniert nicht, da keine Konvertierung von Integer
in int
erfolgt.int
nicht als Typargument für Generika verwenden, daher müsste es sich bei um eine int
-spezifische Methode handeln (oder um böse Tricks zu begehen).Ich glaube, es gibt Bibliotheken, die automatisch generierte Versionen dieser Art von Methoden für alle primitiven Typen haben (d. H. Es gibt eine Vorlage, die für jeden Typ kopiert wird). Es ist hässlich, aber ich fürchte, so ist es :(
Auch wenn die Klasse Arrays
herauskam, bevor Generics in Java eintraf, müsste sie dennoch alle schrecklichen Überladungen enthalten, wenn sie heute eingeführt würde (vorausgesetzt, Sie möchten primitive Arrays verwenden).
Bisher hat noch niemand Streams erwähnt, die in Java 8 hinzugefügt wurden.
int[] array = list.stream().mapToInt(i->i).toArray();
Denkprozess:
Stream#toArray
gibt Object[]
zurück, es ist also nicht das, was wir wollen. Außerdem macht Stream#toArray(IntFunction<A[]> generator)
nicht das, was wir wollen, weil der generische Typ A
nicht das Primitive int
darstellen kann.int
anstelle des Wrappers Integer
handhaben könnte, da seine Methode toArray
höchstwahrscheinlich auch das Array int[]
zurückgibt (etwas anderes wie Object[]
oder sogar boxed Integer[]
wäre hier unnatürlich). Und glücklicherweise hat Java 8 einen solchen Stream, der IntStream
istjetzt müssen wir nur noch herausfinden, wie wir unseren Stream<Integer>
(der von list.stream()
zurückgegeben wird) in diesen glänzenden IntStream
konvertieren. Hier kommt Stream#mapToInt(ToIntFunction<? super T> mapper)
Methode zur Rettung. Alles, was wir tun müssen, ist die Zuordnung von Integer
zu int
. Wir könnten etwas wie Integer#getValue
verwenden, das int
zurückgibt, wie:
mapToInt( (Integer i) -> i.intValue() )
(oder wenn jemand mapToInt(Integer::intValue)
vorzieht)
ein ähnlicher Code kann jedoch mit Unboxing generiert werden, da der Compiler weiß, dass das Ergebnis dieses Lambda int
sein muss (Lambda in mapToInt
ist die Implementierung der Schnittstelle ToIntFunction
, die den Body für die Methode int applyAsInt(T value)
erwartet, die int
zurückgibt).
Wir können also einfach schreiben
mapToInt((Integer i)->i)
Auch da Integer
(Integer i)
eingibt, kann der Compiler darauf schließen, dass List<Integer>#stream()
Stream<Integer>
zurückgibt
mapToInt(i -> i)
Zusätzlich zu Commons Lang können Sie dies mit Guava s Methode Ints.toArray(Collection<Integer> collection)
tun:
List<Integer> list = ...
int[] ints = Ints.toArray(list);
Dies erspart Ihnen die Zwischen-Array-Konvertierung, die Sie für das Commons Lang-Äquivalent benötigen.
Am einfachsten geht das mit Apache Commons Lang . Es gibt eine praktische ArrayUtils-Klasse, die alles kann, was Sie wollen. Verwenden Sie die Methode toPrimitive
mit der Überladung für ein Array von Integer
s.
List<Integer> myList;
... assign and fill the list
int[] intArray = ArrayUtils.toPrimitive(myList.toArray(new Integer[myList.size()]));
Auf diese Weise erfinden Sie das Rad nicht neu. Commons Lang hat sehr viele nützliche Dinge, die Java weggelassen haben. Oben habe ich eine Ganzzahlliste mit der richtigen Größe erstellt. Sie können auch ein statisches Ganzzahl-Array der Länge 0 verwenden und Java ein Array der richtigen Größe zuweisen:
static final Integer[] NO_INTS = new Integer[0];
....
int[] intArray2 = ArrayUtils.toPrimitive(myList.toArray(NO_INTS));
Mit Java 8 haben wir eine einfache Möglichkeit, dies über Streams zu tun ...
Mit der Funktion collections stream()
und dem anschließenden Zuordnen zu ints erhalten Sie einen IntStream. Mit dem IntStream
können wir toArray () aufrufen, was uns int []
gibt.
int [] ints = list.stream().mapToInt(Integer::intValue).toArray();
int[] toIntArray(List<Integer> list) {
int[] ret = new int[list.size()];
int i = 0;
for (Integer e : list)
ret[i++] = e;
return ret;
}
Geringe Änderung des Codes, um eine teure Indexierung der Liste zu vermeiden (da eine Liste nicht unbedingt eine ArrayList ist, sondern eine verknüpfte Liste sein kann, für die der wahlfreie Zugriff teuer ist)
Hier ist Java 8 einzeiliger Code dafür
public int[] toIntArray(List<Integer> intList){
return intList.stream().mapToInt(Integer::intValue).toArray();
}
Wenn Sie einfach ein Integer
einem int
zuordnen, sollten Sie nter Verwendung von Parallelität in Betracht ziehen, da Ihre Zuordnungslogik sich nicht auf Variablen außerhalb ihres Gültigkeitsbereichs stützt.
int[] arr = list.parallelStream().mapToInt(Integer::intValue).toArray();
Sei dir dessen einfach bewusst
Beachten Sie, dass die Parallelität nicht automatisch schneller ist als die serielle Ausführung von Vorgängen. Dies kann jedoch der Fall sein, wenn Sie über genügend Daten und Prozessorkerne verfügen. Während Sie mit Aggregatoperationen Parallelität einfacher implementieren können, liegt es immer noch in Ihrer Verantwortung, zu bestimmen, ob Ihre Anwendung für Parallelität geeignet ist.
Es gibt zwei Möglichkeiten, Ganzzahlen ihrer primitiven Form zuzuordnen:
Über ein ToIntFunction
.
mapToInt(Integer::intValue)
Über explizites nboxing mit Lambda-Ausdruck.
mapToInt(i -> i.intValue())
Über implizites (Auto-) Unboxing mit Lambda-Ausdruck.
mapToInt(i -> i)
Gegeben eine Liste mit einem null
Wert
List<Integer> list = Arrays.asList(1, 2, null, 4, 5);
Es gibt drei Möglichkeiten, mit null
umzugehen:
Filtern Sie die null
Werte heraus, bevor Sie sie zuordnen.
int[] arr = list.parallelStream().filter(Objects::nonNull).mapToInt(Integer::intValue).toArray();
Ordnen Sie die null
Werte einem Standardwert zu.
int[] arr = list.parallelStream().map(i -> i == null ? -1 : i).mapToInt(Integer::intValue).toArray();
Behandle null
innerhalb des Lambda-Ausdrucks.
int[] arr = list.parallelStream().mapToInt(i -> i == null ? -1 : i.intValue()).toArray();
Ich werfe noch einen hier rein. Ich habe mehrere Verwendungen von for-Schleifen bemerkt, aber Sie brauchen nicht einmal etwas in der Schleife. Ich erwähne dies nur, weil die ursprüngliche Frage versuchte, weniger ausführlichen Code zu finden.
int[] toArray(List<Integer> list) {
int[] ret = new int[ list.size() ];
int i = 0;
for( Iterator<Integer> it = list.iterator();
it.hasNext();
ret[i++] = it.next() );
return ret;
}
Wenn Java wie C++ mehrere Deklarationen in einer for-Schleife zulässt, könnten wir einen Schritt weiter gehen und für (int i = 0, Iterator it ...
Am Ende jedoch (dieser Teil ist nur meine Meinung), wenn Sie eine Hilfsfunktion oder -methode haben, um etwas für Sie zu tun, richten Sie es einfach ein und vergessen Sie es. Es kann ein Einzeiler oder zehn sein; Wenn du es nie wieder betrachtest, wirst du den Unterschied nicht erkennen.
Diese einfache Schleife ist immer richtig! keine Bugs
int[] integers = new int[myList.size()];
for (int i = 0; i < integers.length; i++) {
integers[i] = myList.get(i);
}
Es gibt wirklich keine Möglichkeit, das, was Sie versuchen, in einer Zeile zusammenzufassen, da toArray ein Objekt [] zurückgibt und Sie nicht von Object [] nach int [] oder Integer [] nach int [] umwandeln können.
int[] ret = new int[list.size()];
Iterator<Integer> iter = list.iterator();
for (int i=0; iter.hasNext(); i++) {
ret[i] = iter.next();
}
return ret;
versuchen Sie auch Dollar ( überprüfen Sie diese Revision ):
import static com.humaorie.dollar.Dollar.*
...
List<Integer> source = ...;
int[] ints = $(source).convert().toIntArray();
Mit Eclipse Collections können Sie Folgendes tun, wenn Sie eine Liste vom Typ Java.util.List<Integer>
haben:
List<Integer> integers = Lists.mutable.with(1, 2, 3, 4, 5);
int[] ints = LazyIterate.adapt(integers).collectInt(i -> i).toArray();
Assert.assertArrayEquals(new int[]{1, 2, 3, 4, 5}, ints);
Wenn Sie bereits einen Eclipse-Sammlungstyp wie MutableList
haben, können Sie Folgendes tun:
MutableList<Integer> integers = Lists.mutable.with(1, 2, 3, 4, 5);
int[] ints = integers.asLazy().collectInt(i -> i).toArray();
Assert.assertArrayEquals(new int[]{1, 2, 3, 4, 5}, ints);
Hinweis: Ich bin ein Committer für Eclipse-Sammlungen
Ich würde Ihnen empfehlen, die Skelettimplementierung List<?>
aus der Java -Sammlungs-API zu verwenden. Dies scheint in diesem speziellen Fall sehr hilfreich zu sein:
package mypackage;
import Java.util.AbstractList;
import Java.util.Arrays;
import Java.util.Collections;
import Java.util.List;
public class Test {
//Helper method to convert int arrays into Lists
static List<Integer> intArrayAsList(final int[] a) {
if(a == null)
throw new NullPointerException();
return new AbstractList<Integer>() {
@Override
public Integer get(int i) {
return a[i];//autoboxing
}
@Override
public Integer set(int i, Integer val) {
final int old = a[i];
a[i] = val;//auto-unboxing
return old;//autoboxing
}
@Override
public int size() {
return a.length;
}
};
}
public static void main(final String[] args) {
int[] a = {1, 2, 3, 4, 5};
Collections.reverse(intArrayAsList(a));
System.out.println(Arrays.toString(a));
}
}
Hüten Sie sich vor Nachteilen beim Boxen und beim Auspacken
Mit einem Lambda könnten Sie dies tun (kompiliert in JDK Lambda):
public static void main(String ars[]) {
TransformService transformService = (inputs) -> {
int[] ints = new int[inputs.size()];
int i = 0;
for (Integer element : inputs) {
ints[ i++ ] = element;
}
return ints;
};
List<Integer> inputs = new ArrayList<Integer>(5) { {add(10); add(10);} };
int[] results = transformService.transform(inputs);
}
public interface TransformService {
int[] transform(List<Integer> inputs);
}