Bagaimana cara mengubah ArrayList yang berisi Integer ke array int primitif?

297

Saya mencoba untuk mengkonversi ArrayList yang berisi objek Integer ke primitif int [] dengan potongan kode berikut, tetapi ia melemparkan kesalahan waktu kompilasi. Apakah mungkin mengkonversi di Jawa?

List<Integer> x =  new ArrayList<Integer>();
int[] n = (int[])x.toArray(int[x.size()]);
Snehal
sumber
10
Bukan duplikat TEPAT dari pertanyaan itu (walaupun tidak terlalu jauh)
Jonik
1
Ya, ini adalah ArrayList, "duplikat" adalah tentang array normal.
Scott McIntyre
3
Jika Anda tidak memerlukan int primitif, Anda dapat menggunakan: List<Integer> x = new ArrayList<Integer>(); Integer[] n = x.toArray(new Integer[0]);
Evorlor
Kemungkinan duplikat dari Mengonversi array objek ke array tipe primitif mereka
cellepo

Jawaban:

219

Anda dapat mengonversi, tetapi saya rasa tidak ada yang dibangun untuk melakukannya secara otomatis:

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;
}

(Perhatikan bahwa ini akan melempar NullPointerException jika salah satu integersatau elemen di dalamnya null.)

Sunting: Sesuai komentar, Anda mungkin ingin menggunakan daftar iterator untuk menghindari biaya buruk dengan daftar seperti 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
sumber
21
Mungkin lebih baik untuk beralih menggunakan iterator Daftar (dengan masing-masing) untuk menghindari hit kinerja pada daftar yang aksesnya bukan O (1).
Matthew Willis
@ Matius: Ya, mungkin - akan mengedit untuk memberikan itu sebagai alternatif.
Jon Skeet
1
Anda juga dapat memanfaatkan fakta bahwa ArrayList mengimplementasikan Iterable (melalui warisan Collection) dan melakukan: for (int n: integer) {ret [counter ++] = n; } ... dan inisialisasi penghitung int = 0;
gardarh
8
jauh lebih mudah sekarang di Java8:integers.stream().mapToInt(Integer::valueOf).toArray
Manish Patel
241

Jika Anda menggunakan ada juga cara lain untuk melakukan ini.

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

Apa yang dilakukannya adalah:

  • dapatkan Stream<Integer>dari daftar
  • memperoleh IntStreamdengan memetakan setiap elemen ke dirinya sendiri (fungsi identitas), menghapus kotak intnilai yang disimpan oleh setiap Integerobjek (dilakukan secara otomatis sejak Java 5)
  • mendapatkan array intdengan menelepontoArray

Anda juga dapat secara eksplisit menelepon intValuemelalui referensi metode, yaitu:

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

Perlu juga disebutkan bahwa Anda bisa mendapatkan NullPointerExceptionjika Anda memiliki nullreferensi dalam daftar. Ini bisa dengan mudah dihindari dengan menambahkan kondisi penyaringan ke pipa aliran seperti ini:

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

Contoh:

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.
sumber
Saya melihat ini dapat digunakan untuk doubletipe; apakah tidak ada yang setara untuk floatjenis?
code_dredd
Melihat manfaat Java 8 oleh Anda penjelasan yang rumit.
Eugene
Dan inilah mengapa Java 8+ Stream API itu indah.
Pranav A.
67

Google Jambu

Google Guava menyediakan cara yang rapi untuk melakukan ini dengan menelepon Ints.toArray.

List<Integer> list = ...;
int[] values = Ints.toArray(list);
Snehal
sumber
6
Saya pikir ini akan menjadi jawaban bagi saya - saya akan mengambil perpustakaan atas fungsi salin-tempel setiap hari .. terutama perpustakaan yang kemungkinan besar sudah menggunakan proyek berukuran layak. Saya harap jawaban ini mendapat lebih banyak suara dan visibilitas di masa depan.
Sean Connolly
61

Apache Commons memiliki kelas ArrayUtils, yang memiliki metode toPrimitive () yang melakukan hal ini.

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]));

Namun, seperti yang ditunjukkan Jon, cukup mudah untuk melakukannya sendiri daripada menggunakan perpustakaan eksternal.

Björn
sumber
2
Perhatikan bahwa pendekatan ini akan membuat dua salinan lengkap dari urutan: satu Integer [] dibuat oleh toArray, dan satu int [] dibuat di dalam toPrimitive. Jawaban lain dari Jon hanya membuat dan mengisi satu array. Sesuatu untuk dipertimbangkan jika Anda memiliki daftar besar, dan kinerja itu penting.
paraquat
Saya mengukur kinerja menggunakan ArrayUtils vs java murni dan pada daftar kecil (<25 elemen) java murni lebih dari 100 kali lebih cepat. Untuk elemen 3k java murni masih hampir 2 kali lebih cepat ... (ArrayList <Integer> -> int [])
Oskar Lund
@paraquat & Oskar Lund yang sebenarnya tidak benar. Ya, kode yang diberikan akan membuat dua array, tetapi pendekatan ini tidak. Masalah dalam kode ini di sini adalah penggunaan array panjang nol sebagai argumen. The ArrayList.toArray kode sumber menunjukkan bahwa jika isi akan cocok, array asli akan digunakan. Saya pikir dalam perbandingan yang adil Anda akan menemukan metode ini seefisien (jika tidak lebih) dan, tentu saja, lebih sedikit kode untuk dipelihara.
Sean Connolly
PS: posting terkait yang bagus
Sean Connolly
1
Waht adalah tujuan Integer baru [0]?
Adam Hughes
41

Saya percaya iterasi menggunakan iterator Daftar adalah ide yang lebih baik, karena list.get(i)dapat memiliki kinerja yang buruk tergantung pada implementasi Daftar:

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
sumber
6

menggunakan Dollar seharusnya cukup sederhana:

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

Saya berencana untuk meningkatkan DSL untuk menghapus toArray()panggilan menengah

dfa
sumber
1
Hei, hanya ingin mengatakan saya belum melihat Dollar sebelumnya, tapi saya pasti mencobanya di proyek saya berikutnya. Itu api kecil yang bagus yang telah kamu tuju, tetap bekerja dengan baik :)
Bart Vandendriessche
4

Ini berfungsi baik untuk saya :)

Ditemukan di 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
sumber
3

Ini membingungkan saya bahwa kami mendorong metode kustom satu kali setiap kali perpustakaan yang sangat baik, digunakan dengan baik seperti Apache Commons telah memecahkan masalah. Meskipun solusinya sepele jika tidak absurd, itu tidak bertanggung jawab untuk mendorong perilaku seperti itu karena pemeliharaan jangka panjang dan aksesibilitas.

Pergilah dengan Apache Commons

Andrew F.
sumber
7
Saya setuju dengan komentator sebelumnya. Anda tidak hanya menyeret di Apache Commons, tetapi juga dengan mudah diterjemahkan menjadi satu set besar dependensi transitif yang juga perlu diseret. Baru-baru ini saya bisa menghapus # dependensi yang menakjubkan dengan mengganti satu baris kode :-( Ketergantungan mahal dan menulis kode dasar seperti ini adalah praktik yang baik
Peter Kriens
1
Setuju dengan @PeterKriens. Jika ada, kesalahannya adalah di Jawa karena tidak mendukung konversi sederhana seperti ini dalam tipe data standar
Adam Hughes
3

Jika Anda menggunakan Koleksi Eclipse , Anda bisa menggunakan collectInt()metode ini untuk beralih dari wadah objek ke wadah int primitif.

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());

Jika Anda dapat mengonversi ArrayListke FastList, Anda dapat menyingkirkan adaptor.

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

Catatan: Saya pengendara untuk koleksi Eclipse.

Craig P. Motlin
sumber
3

Java 8:

int[] intArr = Arrays.stream(integerList).mapToInt(i->i).toArray();
EssaidiM
sumber
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));

Keluaran:

Array int primitif: [7, 9, 13]

Karya-karya yang sama untuk berbagai longatau double, tetapi tidak untuk array boolean, char, byte, shortatau float. Jika Anda memiliki daftar yang sangat besar, bahkan ada parallelSetAllmetode yang dapat Anda gunakan sebagai gantinya.

Bagi saya ini bagus dan cukup elgant sehingga saya tidak ingin mendapatkan perpustakaan eksternal atau menggunakan stream untuk itu.

Tautan dokumentasi: Arrays.setAll(int[], IntUnaryOperator)

Ole VV
sumber
1

Anda cukup menyalinnya ke sebuah array:

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

Tidak terlalu mewah; tapi, hei, itu berhasil ...

sagiksp
sumber
1

Solusi satu garis yang sangat sederhana adalah:

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

Segmen kode ini berfungsi untuk saya, coba ini:

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

Layak untuk menyebutkan ArrayList harus dinyatakan seperti ini:

ArrayList<Integer> list = new ArrayList<>();
pengguna3444748
sumber
5
Halo hanya pengingat lembut bahwa OP ingin array primitif bukan array Object.
OLIVER.KOO
3
Primitive int bukan 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
sumber
1
Jawaban ini tidak berfungsi, ia mengembalikan array dengan elemen tunggal alih-alih beberapa elemen.
Mysticial
Mengapa menggunakan StringBuffer? Mengapa mengkonversi Integer ke String dan kemudian ke Integer dan kemudian ke int dan kemudian ke Integer lagi? Mengapa menggunakan array dengan elemen tunggal di dalamnya, dan mengapa mengulangi array elemen tunggal saat itu hanya mengandung satu elemen? Mengapa melemparkan Integer ke Objek di lingkaran luar? Ada banyak sekali pertanyaan di sini. Apakah @CodeMadness hanya akun troll?
Victor Zamanian
-5
Integer[] arr = (Integer[]) x.toArray(new Integer[x.size()]);

akses arrseperti biasa int[].

snn
sumber
5
ini tidak menjawab pertanyaan, pertanyaannya adalah tentang mengubah ke tipe primitif (int)
Asaf