Dit is vergelijkbaar met deze vraag:
Hoe converteer ik int[] naar Integer[] in Java?
Ik ben nieuw op Java. Hoe kan ik een List<Integer>
converteren naar int[]
in Java? Ik ben in de war omdat List.toArray()
eigenlijk een Object[]
retourneert, die kan worden gecast naar onder Integer[]
of int[]
.
Op dit moment gebruik ik een lus om dit te doen:
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;
}
Ik weet zeker dat er een betere manier is om dit te doen.
Antwoord 1, autoriteit 100%
Helaas geloof ik niet dat er echt iseen betere manier om dit te doen vanwege de aard van Java’s omgang met primitieve typen, boxing, arrays en generieke middelen. In het bijzonder:
List<T>.toArray
werkt niet omdat er geen conversie is vanInteger
naarint
- Je kunt
int
niet gebruiken als typeargument voor generieke geneesmiddelen, dus het zou moeteneenint
-specifieke methode zijn (of een die reflectie gebruikte om vervelende bedrog uit te voeren).
Ik geloof dat er bibliotheken zijn die automatisch gegenereerde versies van dit soort methode hebben voor alle primitieve typen (d.w.z. er is een sjabloon dat voor elk type wordt gekopieerd). Het is lelijk, maar zo is het ben ik bang 🙁
Hoewel de Arrays
klasse uitkwam voordat generieke geneesmiddelen in Java arriveerden, zou het nog steeds alle vreselijke overbelastingen moeten bevatten als het vandaag zou worden geïntroduceerd (ervan uitgaande dat je primitieve arrays wilt gebruiken).
Antwoord 2, autoriteit 94%
Niemand heeft het nog over streams toegevoegd in Java 8, dus hier komt het:
int[] array = list.stream().mapToInt(i->i).toArray();
//OR
//int[] array = list.stream().mapToInt(Integer::intValue).toArray();
Denkproces:
-
eenvoudige
Stream#toArray
retourneertObject[]
, dus het is niet wat we willen. OokStream#toArray(IntFunction<A[]> generator)
doet niet wat we willen omdat generiek typeA
primitieveint
-
dus het zou leuk zijn om een stream te hebben die het primitieve type
int
aankan in plaats van wrapperInteger
, omdat hettoArray
is methode zal hoogstwaarschijnlijk ookint[]
array retourneren (het retourneren van iets anders zoalsObject[]
of zelfs boxedInteger[]
zou hier onnatuurlijk zijn) . En gelukkig heeft Java 8 zo’n stream dieIntStream
-
Dus nu hoeven we alleen nog uit te zoeken hoe we onze
Stream<Integer>
moeten converteren (die wordt geretourneerd doorlist.stream()
) naar die glanzendeIntStream
. HierStream#mapToInt(ToIntFunction<? super T> mapper)
-methode komt te hulp. Het enige wat we hoeven te doen is de mapping door te geven vanInteger
naarint
.We zouden zoiets kunnen gebruiken als
Integer#intValue
watint
als resultaat geeft:mapToInt( (Integer i) -> i.intValue() )
(of als iemand de voorkeur geeft aan
mapToInt(Integer::intValue)
)maar vergelijkbare code kan worden gegenereerd met behulp van unboxing, omdat de compiler weet dat het resultaat van deze lambda
int
moet zijn (lambda inmapToInt
is de implementatie vanToIntFunction
interface die body verwacht voorint applyAsInt(T value)
methode die naar verwachtingint
zal retourneren).Dus we kunnen gewoon schrijven
mapToInt((Integer i)->i)
Ook aangezien
Integer
(Integer i)
typt, kan worden afgeleid door de compiler omdatList<Integer>#stream()
Stream<Integer>
we kunnen het ook overslaan, wat ons achterlaat metmapToInt(i -> i)
Antwoord 3, autoriteit 87%
Naast Commons Lang kun je dit doen met Guava‘s methode Ints.toArray(Collection<Integer> collection)
:
List<Integer> list = ...
int[] ints = Ints.toArray(list);
Hiermee hoeft u niet de tussenliggende array-conversie uit te voeren die het equivalent van Commons Lang zelf vereist.
Antwoord 4, autoriteit 72%
De eenvoudigste manier om dit te doen is door gebruik te maken van Apache Commons Lang. Het heeft een handige ArrayUtils-klasse die kan doen wat je wilt. Gebruik de toPrimitive
methode met de overbelasting voor een array van Integer
s.
List<Integer> myList;
... assign and fill the list
int[] intArray = ArrayUtils.toPrimitive(myList.toArray(new Integer[myList.size()]));
Zo hoef je het wiel niet opnieuw uit te vinden. Commons Lang heeft een groot aantal nuttige dingen die Java heeft weggelaten. Hierboven heb ik ervoor gekozen om een Integer-lijst van de juiste maat te maken. U kunt ook een statische Integer-array met een lengte van 0 gebruiken en Java een array van de juiste grootte laten toewijzen:
static final Integer[] NO_INTS = new Integer[0];
....
int[] intArray2 = ArrayUtils.toPrimitive(myList.toArray(NO_INTS));
Antwoord 5, autoriteit 29%
Java 8heeft ons een gemakkelijke manier gegeven om dit te doen via streams…
Door de functie collections stream()
te gebruiken en vervolgens toe te wijzen aan ints, krijg je een IntStream. Met de IntStream
kunnen we toArray() aanroepen wat ons int []
geeft
int [] ints = list.stream().mapToInt(Integer::intValue).toArray();
Antwoord 6, autoriteit 24%
int[] toIntArray(List<Integer> list) {
int[] ret = new int[list.size()];
int i = 0;
for (Integer e : list)
ret[i++] = e;
return ret;
}
Een kleine wijziging in uw code om dure lijstindexering te voorkomen (aangezien een lijst niet noodzakelijk een ArrayList is, maar een gelinkte lijst kan zijn, waarvoor willekeurige toegang duur is)
Antwoord 7, autoriteit 5%
Hier is Java 8eenregelige code hiervoor
public int[] toIntArray(List<Integer> intList){
return intList.stream().mapToInt(Integer::intValue).toArray();
}
Antwoord 8, autoriteit 4%
Als u eenvoudig een Integer
aan een int
koppelt, moet u overwegen met behulp van parallellisme, aangezien uw toewijzingslogica niet afhankelijk is van variabelen buiten het bereik ervan.
int[] arr = list.parallelStream().mapToInt(Integer::intValue).toArray();
Wees je hiervan bewust
Houd er rekening mee dat parallellisme niet automatisch sneller is dan het serieel uitvoeren van bewerkingen, hoewel het dat wel kan zijn als je genoeg data en processorcores hebt. Hoewel u met geaggregeerde bewerkingen parallellisme gemakkelijker kunt implementeren, is het nog steeds uw verantwoordelijkheid om te bepalen of uw toepassing geschikt is voor parallellisme.
Er zijn twee manieren om gehele getallen toe te wijzen aan hun primitieve vorm:
-
Via een
ToIntFunction
.mapToInt(Integer::intValue)
-
Via expliciete unboxingmet lambda-expressie.
mapToInt(i -> i.intValue())
-
Via impliciete (automatische) unboxing met lambda-expressie.
mapToInt(i -> i)
Gegeven een lijst met een null
waarde
List<Integer> list = Arrays.asList(1, 2, null, 4, 5);
Hier zijn drie opties om null
te verwerken:
-
Filter de
null
-waarden voor het toewijzen.int[] arr = list.parallelStream().filter(Objects::nonNull).mapToInt(Integer::intValue).toArray();
-
Wijs de
null
-waarden toe aan een standaardwaarde.int[] arr = list.parallelStream().map(i -> i == null ? -1 : i).mapToInt(Integer::intValue).toArray();
-
Verwerk
null
binnen de lambda-expressie.int[] arr = list.parallelStream().mapToInt(i -> i == null ? -1 : i.intValue()).toArray();
Antwoord 9, autoriteit 3%
Deze eenvoudige lus is altijd correct! geen fouten
int[] integers = new int[myList.size()];
for (int i = 0; i < integers.length; i++) {
integers[i] = myList.get(i);
}
Antwoord 10, autoriteit 3%
Ik gooi er nog een in. Ik heb verschillende toepassingen van for-lussen opgemerkt, maar je hebt niet eens iets nodig in de lus. Ik vermeld dit alleen omdat de oorspronkelijke vraag probeerde minder uitgebreide code te vinden.
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;
}
Als Java meerdere declaraties in een for-lus toestaat zoals C++ dat doet, zouden we een stap verder kunnen gaan en doen for(int i = 0, Iterator it…
Uiteindelijk echter (dit deel is slechts mijn mening), als je een helpende functie of methode wilt hebben om iets voor je te doen, stel het dan gewoon in en vergeet het. Het kan een one-liner of tien zijn; als je er nooit meer naar kijkt, weet je het verschil niet.
Antwoord 11, autoriteit 2%
Er is echt geen manier om “one-lining” te geven aan wat u probeert te doen, omdat toArray een Object[] retourneert en u niet kunt casten van Object[] naar int[] of Integer[] naar int[]
Antwoord 12, autoriteit 2%
int[] ret = new int[list.size()];
Iterator<Integer> iter = list.iterator();
for (int i=0; iter.hasNext(); i++) {
ret[i] = iter.next();
}
return ret;
Antwoord 13
probeer ook Dollar(controleer deze revisie):
import static com.humaorie.dollar.Dollar.*
...
List<Integer> source = ...;
int[] ints = $(source).convert().toIntArray();
Antwoord 14
Ik raad je aan om de List<?>
skeletimplementatie van de Java Collections API te gebruiken, het lijkt in dit specifieke geval heel nuttig te zijn:
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));
}
}
Pas op voor de nadelen van boksen/unboxen
Antwoord 15
Met Eclipse Collectionskunt u het volgende doen als u een lijst van het type java.util.List<Integer>
:
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);
Als je al een Eclipse Collections-type hebt, zoals MutableList
, je kunt het volgende doen:
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);
Opmerking: ik ben een toegewijde voor Eclipse Collections
Antwoord 16
Met een lambda zou je dit kunnen doen (compileert 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);
}