วิธีการแปลง ArrayList ที่มีจำนวนเต็มเป็นอาร์เรย์ดั้งเดิม


297

ฉันพยายามแปลง ArrayList ที่มีวัตถุ Integer เป็น primitive int [] ด้วยโค้ดต่อไปนี้ แต่กำลังโยนข้อผิดพลาดในการคอมไพล์ เป็นไปได้ไหมที่จะแปลงเป็น Java?

List<Integer> x =  new ArrayList<Integer>();
int[] n = (int[])x.toArray(int[x.size()]);

10
ไม่ได้เป็นที่แน่นอนซ้ำของคำถามว่า (แม้ว่าจะไม่ไกลมากอย่างใดอย่างหนึ่ง)
Jonik

1
ใช่นี่คือ ArrayList "ซ้ำ" เป็นเรื่องเกี่ยวกับอาร์เรย์ปกติ
Scott McIntyre

3
หากคุณไม่ต้องการ ints ดั้งเดิมคุณสามารถใช้: List<Integer> x = new ArrayList<Integer>(); Integer[] n = x.toArray(new Integer[0]);
Evorlor

คำตอบ:


219

คุณสามารถแปลงได้ แต่ฉันไม่คิดว่าจะมีสิ่งใดที่จะทำโดยอัตโนมัติ:

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

(โปรดทราบว่าสิ่งนี้จะส่ง NullPointerException หากintegersองค์ประกอบใด ๆ หรืออยู่ภายในนั้นnull)

แก้ไข: ตามความคิดเห็นคุณอาจต้องการใช้ตัววนซ้ำรายการเพื่อหลีกเลี่ยงค่าใช้จ่ายที่น่ารังเกียจด้วยรายการเช่น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;
}

21
อาจเป็นการดีกว่าที่จะวนซ้ำโดยใช้ตัววนซ้ำของรายการ (พร้อมสำหรับแต่ละรายการ) เพื่อหลีกเลี่ยงปัญหาที่เกิดขึ้นกับรายการที่มีการเข้าถึงไม่ใช่ O (1)
Matthew Willis

@ Matthew: ใช่เป็นไปได้ - จะแก้ไขเพื่อให้เป็นทางเลือก
Jon Skeet

1
คุณยังสามารถใช้ความจริงที่ ArrayList ใช้ Iterable (ผ่านการสืบทอดการรวบรวม) และทำ: สำหรับ (int n: จำนวนเต็ม) {ret [counter ++] = n; } ... และเริ่มต้น int counter = 0;
gardarh

8
ง่ายกว่าตอนนี้ใน Java8:integers.stream().mapToInt(Integer::valueOf).toArray
Manish Patel

241

หากคุณกำลังใช้ นอกจากนี้ยังมีวิธีอื่นในการทำเช่นนี้

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

มันคืออะไร:

  • ได้รับStream<Integer>จากรายการ
  • ได้รับIntStreamโดยการแมปองค์ประกอบแต่ละตัวเอง (ฟังก์ชั่นเอกลักษณ์), การแกะกล่องintค่าไว้โดยIntegerวัตถุแต่ละชิ้น (ทำโดยอัตโนมัติตั้งแต่ Java 5)
  • รับอาร์เรย์intโดยการโทรtoArray

คุณสามารถโทรหาอย่างชัดเจนintValueผ่านการอ้างอิงวิธีการเช่น:

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

เป็นมูลค่าการกล่าวขวัญว่าคุณจะได้รับNullPointerExceptionถ้าคุณมีnullการอ้างอิงใด ๆในรายการ สิ่งนี้สามารถหลีกเลี่ยงได้อย่างง่ายดายโดยการเพิ่มเงื่อนไขการกรองไปยังไปป์ไลน์เช่นนี้:

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

ตัวอย่าง:

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]

ฉันเห็นสิ่งนี้สามารถใช้สำหรับdoubleประเภท; จะไม่เทียบเท่าfloatประเภท?
code_dredd

เห็นประโยชน์ของ Java 8 โดยคุณอธิบายอย่างละเอียด
ยูจีน

และนี่คือสาเหตุที่ Java 8+ Stream API นั้นสวยงาม
.

67

Google Guava

Google ฝรั่งInts.toArrayให้เป็นวิธีที่เรียบร้อยจะทำเช่นนี้โดยการโทร

List<Integer> list = ...;
int[] values = Ints.toArray(list);

6
ฉันคิดว่านี่จะเป็นคำตอบสำหรับฉัน - ฉันจะใช้ห้องสมุดมากกว่าฟังก์ชั่นการคัดลอกวางทุกวัน .. โดยเฉพาะอย่างยิ่งห้องสมุดที่โครงการขนาดที่เหมาะสมน่าจะใช้อยู่แล้ว ฉันหวังว่าคำตอบนี้จะได้รับการโหวตมากขึ้นและมองเห็นได้ในอนาคต
Sean Connolly

61

Apache Commons มีคลาส ArrayUtils ซึ่งมีเมธอด toPrimitive () ที่ทำสิ่งนี้

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

อย่างไรก็ตามอย่างที่จอนแสดงมันค่อนข้างง่ายที่จะทำด้วยตัวเองแทนที่จะใช้ห้องสมุดภายนอก


2
โปรดทราบว่าวิธีการนี้จะทำสำเนาตามลำดับสองชุด: หนึ่งจำนวนเต็ม [] สร้างโดย toArray และหนึ่ง int [] สร้างขึ้นภายใน toPrimitive คำตอบอื่น ๆ จากจอนสร้างและเติมอาเรย์เดียวเท่านั้น สิ่งที่ต้องพิจารณาหากคุณมีรายการขนาดใหญ่และประสิทธิภาพเป็นสิ่งสำคัญ
paraquat

ฉันวัดประสิทธิภาพโดยใช้ ArrayUtils vs pure java และในรายการขนาดเล็ก (<25 องค์ประกอบ) java บริสุทธิ์จะเร็วกว่า 100 เท่า สำหรับองค์ประกอบ 3k pure java ยังคงเร็วกว่าเกือบ 2 เท่า ... (ArrayList <Integer> -> int [])
Oskar Lund

@paraquat & Oskar Lund ที่ไม่ถูกต้อง ใช่รหัสที่ให้มาจะสร้างสองอาร์เรย์ แต่วิธีนี้ไม่ได้ ปัญหาในรหัสนี้ที่นี่คือการใช้อาร์เรย์ความยาวเป็นศูนย์เป็นอาร์กิวเมนต์ แหล่ง ArrayList.toArray รหัสที่แสดงให้เห็นว่าถ้าเนื้อหาจะพอดีกับอาร์เรย์เดิมจะถูกนำมาใช้ ฉันคิดว่าในการเปรียบเทียบที่เป็นธรรมคุณจะพบว่าวิธีนี้มีประสิทธิภาพ (ถ้าไม่มาก) และแน่นอนว่าต้องรักษาโค้ดให้น้อยลง
ฌอนคอนนอลลี่


1
Waht คือจุดประสงค์ของ Integer ใหม่ [0]?
Adam Hughes

41

ฉันเชื่อว่าการวนซ้ำโดยใช้ตัววนซ้ำของรายการเป็นแนวคิดที่ดีกว่าเนื่องจากlist.get(i)สามารถมีประสิทธิภาพต่ำขึ้นอยู่กับการใช้งานรายการ:

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

6

การใช้Dollarควรง่ายมาก:

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

ฉันวางแผนที่จะปรับปรุง DSL เพื่อที่จะลบการtoArray()โทรระหว่างกลาง


1
เฮ้แค่อยากจะบอกว่าฉันไม่เคยเห็นดอลล่าร์มาก่อน แต่ฉันจะลองทำโปรเจ็กต์ต่อไปของฉัน นั่นเป็น API น้อยดีที่คุณได้ไปที่นั่นให้การทำงานที่ดี :)
บาร์ต Vandendriessche

4

มันใช้งานได้ดีสำหรับฉัน :)

พบได้ที่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));
    }
}

3

มันทำให้ฉันสับสนว่าเราสนับสนุนวิธีการที่กำหนดเองแบบครั้งเดียวทุกครั้งที่ห้องสมุดที่ใช้งานได้ดีอย่างสมบูรณ์แบบอย่าง Apache Commons ได้แก้ปัญหาไปแล้ว แม้ว่าวิธีการแก้ปัญหาจะไม่สำคัญหากไม่ไร้สาระ แต่ก็ไม่รับผิดชอบในการส่งเสริมพฤติกรรมดังกล่าวเนื่องจากการบำรุงรักษาและการเข้าถึงในระยะยาว

เพียงไปกับApache Commons


7
ฉันเห็นด้วยกับผู้แสดงความคิดเห็นก่อนหน้านี้ คุณไม่เพียง แต่ลากใน Apache Commons เท่านั้น แต่มันแปลได้อย่างง่ายดายเป็นชุดใหญ่ของการพึ่งพาสกรรมกริยาที่ต้องลากเข้ามาเมื่อเร็ว ๆ นี้ฉันสามารถลบ # ของการพึ่งพาที่น่าทึ่งได้ด้วยการแทนที่รหัสหนึ่งบรรทัด :-( การพึ่งพามีราคาแพงและ การเขียนโค้ดพื้นฐานแบบนี้เป็นการปฏิบัติที่ดี
Peter Kriens

1
เห็นด้วยกับ @PeterKriens หากมีสิ่งใดเกิดขึ้นความผิดพลาดใน Java ที่ไม่สนับสนุนการแปลงอย่างง่ายเช่นนี้ในประเภทข้อมูลมาตรฐาน
Adam Hughes

3

หากคุณกำลังใช้Eclipse Collectionsคุณสามารถใช้collectInt()วิธีการเปลี่ยนจากที่เก็บวัตถุเป็นที่เก็บแบบดั้งเดิม

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

หากคุณสามารถแปลงArrayListเป็น a FastListคุณสามารถกำจัดอะแดปเตอร์

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

หมายเหตุ:ฉันเป็นคอมมิชชันสำหรับคอลเลกชัน Eclipse



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

เอาท์พุท:

Array of ints ดั้งเดิม: [7, 9, 13]

การทำงานเหมือนกันสำหรับอาร์เรย์ของlongหรือdoubleแต่ไม่ใช่สำหรับอาร์เรย์boolean, char, byte, หรือshort floatหากคุณมีรายการใหญ่มากมีparallelSetAllวิธีที่คุณอาจใช้แทน

สำหรับฉันนี่เป็นสิ่งที่ดีและช่างดีพอที่ฉันจะไม่ต้องการรับห้องสมุดภายนอกหรือใช้สตรีมสำหรับมัน

ลิงค์เอกสาร: Arrays.setAll(int[], IntUnaryOperator)


1

คุณสามารถคัดลอกไปยังอาร์เรย์:

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

ไม่แฟนซีเกินไป แต่เฮ้มันใช้งานได้ ...


1

โซลูชันบรรทัดเดียวที่ง่ายมากคือ:

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

0

ส่วนรหัสนี้ใช้งานได้สำหรับฉันลองสิ่งนี้:

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

น่าจะกล่าวถึง ArrayList ควรประกาศเช่นนี้:

ArrayList<Integer> list = new ArrayList<>();

5
สวัสดีเป็นเพียงตัวเตือนที่อ่อนโยนว่า OP ต้องการอาร์เรย์ดั้งเดิมไม่ใช่อาร์เรย์วัตถุ
OLIVER.KOO

3
ดั้งเดิม int ไม่ wrapper จำนวนเต็ม!
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());
    }

1
คำตอบนี้ใช้ไม่ได้ แต่จะส่งคืนอาร์เรย์ที่มีองค์ประกอบเดียวแทนที่จะเป็นหลายองค์ประกอบ
Mysticial

ทำไมต้องใช้ StringBuffer เหตุใดจึงแปลงค่าจำนวนเต็มเป็นสตริงจากนั้นเป็นจำนวนเต็มจากนั้นเป็นจำนวนเต็มและเป็นจำนวนเต็มอีกครั้ง เหตุใดจึงต้องใช้อาร์เรย์ที่มีองค์ประกอบเดียวในนั้นและทำไมจึงวนซ้ำอาร์เรย์องค์ประกอบเดียวนั้นเมื่อมันมีเพียงองค์ประกอบเดียว ทำไมจึงเลือก Integers to Objects ในลูปภายนอก มีคำถามมากมายที่นี่ @CodeMadness เป็นเพียงบัญชีหมุนรอบหรือไม่?
Victor Zamanian

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

เข้าถึงเหมือนปกติarrint[]


5
นี้ไม่ตอบคำถามคำถามคือเกี่ยวกับการแปลงเป็นประเภทดั้งเดิม (int)
Asaf
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.