Làm cách nào để chuyển đổi một ArrayList chứa Integers thành mảng int nguyên thủy?


297

Tôi đang cố gắng chuyển đổi một ArrayList chứa các đối tượng Integer thành int nguyên thủy [] với đoạn mã sau, nhưng nó đang gây ra lỗi thời gian biên dịch. Có thể chuyển đổi trong Java?

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

10
Không phải là một bản sao chính xác của câu hỏi đó (mặc dù cũng không xa lắm)
Jonik

1
Vâng, đây là một ArrayList, "trùng lặp" là về một mảng bình thường.
Scott McIntyre

3
Nếu bạn không cần số nguyên thủy, bạn có thể sử dụng: List<Integer> x = new ArrayList<Integer>(); Integer[] n = x.toArray(new Integer[0]);
Evorlor

Câu trả lời:


219

Bạn có thể chuyển đổi, nhưng tôi không nghĩ có bất cứ điều gì được tích hợp để thực hiện tự động:

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

(Lưu ý rằng điều này sẽ ném NullPulumException nếu có integershoặc bất kỳ phần tử nào trong đó null.)

EDIT: Theo nhận xét, bạn có thể muốn sử dụng trình lặp danh sách để tránh các chi phí khó chịu với các danh sách như 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
Có thể tốt hơn để lặp lại bằng cách sử dụng Trình lặp của Danh sách (với mỗi lần lặp) để tránh các lần truy cập hiệu suất trên các danh sách có quyền truy cập không phải là O (1).
Matthew Willis

@Matthew: Có, có thể - sẽ chỉnh sửa để cung cấp thay thế.
Jon Skeet

1
Bạn cũng có thể sử dụng thực tế ArrayList thực hiện Iterable (thông qua thừa kế Bộ sưu tập) và do: for (int n: số nguyên) {ret [counter ++] = n; } ... và khởi tạo int counter = 0;
vườn

8
bây giờ dễ dàng hơn nhiều trong Java8:integers.stream().mapToInt(Integer::valueOf).toArray
Manish Patel

241

Nếu bạn đang sử dụng cũng có một cách khác để làm điều này.

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

Những gì nó làm là:

  • nhận được Stream<Integer>từ danh sách
  • có được một IntStreambằng cách ánh xạ từng phần tử vào chính nó (hàm nhận dạng), bỏ hộp intgiữ giá trị của từng Integerđối tượng (được thực hiện tự động kể từ Java 5)
  • nhận được mảng intbằng cách gọitoArray

Bạn cũng có thể gọi một cách rõ ràng intValuethông qua một tham chiếu phương thức, nghĩa là:

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

Điều đáng nói là bạn có thể nhận được NullPointerExceptionnếu bạn có bất kỳ nulltài liệu tham khảo nào trong danh sách. Điều này có thể dễ dàng tránh được bằng cách thêm một điều kiện lọc vào đường ống dẫn như thế này:

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

Thí dụ:

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]

Tôi thấy điều này có thể được sử dụng cho doublecác loại; không có tương đương cho floatcác loại?
code_dredd

Nhận thấy lợi ích của Java 8 do bạn giải thích chi tiết.
Eugene

Và đây là lý do tại sao API Java 8+ Stream rất đẹp.
Pranav A.

67

Quả ổi

Google Guava cung cấp một cách gọn gàng để làm điều này bằng cách gọi Ints.toArray.

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

6
Tôi nghĩ rằng đây sẽ là câu trả lời cho tôi - Tôi sẽ đưa thư viện qua chức năng sao chép bất kỳ ngày nào .. đặc biệt là thư viện mà một dự án có quy mô khá có thể đã sử dụng. Tôi hy vọng câu trả lời này sẽ nhận được nhiều lượt bình chọn và khả năng hiển thị hơn trong tương lai.
Sean Connolly

61

Apache Commons có một lớp ArrayUtils, có một phương thức toPrimitive () thực hiện chính xác điều này.

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

Tuy nhiên, như Jon chỉ ra, việc tự làm điều này khá dễ dàng thay vì sử dụng các thư viện bên ngoài.


2
Lưu ý rằng cách tiếp cận này sẽ tạo hai bản sao hoàn chỉnh của chuỗi: một Integer [] được tạo bởi toArray và một int [] được tạo bên trong toPrimitive. Câu trả lời khác từ Jon chỉ tạo và điền vào một mảng. Một cái gì đó để xem xét nếu bạn có danh sách lớn, và hiệu suất là quan trọng.
paraquat

Tôi đã đo hiệu suất bằng cách sử dụng ArrayUtils so với java thuần và trên các danh sách nhỏ (<25 phần tử) java thuần nhanh hơn 100 lần. Đối với các phần tử 3k, java thuần vẫn nhanh hơn gần 2 lần ... (ArrayList <Integer> -> int [])
Oskar Lund

@paraquat & Oskar Lund không thực sự chính xác. Có, mã được cung cấp sẽ tạo ra hai mảng, nhưng cách tiếp cận này thì không. Vấn đề trong mã này ở đây là việc sử dụng một mảng có độ dài bằng không làm đối số. Các mã nguồn ArrayList.toArray cho thấy nếu các nội dung sẽ phù hợp, các mảng ban đầu sẽ được sử dụng. Tôi nghĩ rằng trong một so sánh công bằng, bạn sẽ thấy phương pháp này hiệu quả (nếu không phải là nhiều hơn) và tất nhiên, ít mã hơn để duy trì.
Sean Connolly


1
Waht là mục đích của Integer mới [0]?
Adam Hughes

41

Tôi tin rằng việc lặp lại bằng cách sử dụng Trình lặp của Danh sách là một ý tưởng tốt hơn, vì list.get(i)có thể có hiệu suất kém tùy thuộc vào việc thực hiện Danh sách:

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

sử dụng Dollar nên khá đơn giản:

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

Tôi đang lên kế hoạch cải thiện DSL để loại bỏ toArray()cuộc gọi trung gian


1
Này, chỉ muốn nói rằng tôi chưa từng thấy Dollar trước đây, nhưng tôi chắc chắn sẽ thử nó trong dự án tiếp theo của tôi. Đó là một api nhỏ tiện lợi mà bạn đã đến đó, hãy tiếp tục làm tốt :)
Bart Vandendriessche

4

Điều này làm việc tốt cho tôi :)

Tìm thấy tại 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

Điều làm tôi hoang mang là chúng tôi khuyến khích các phương thức tùy chỉnh một lần bất cứ khi nào một thư viện hoàn toàn tốt, được sử dụng tốt như Apache Commons đã giải quyết được vấn đề này. Mặc dù giải pháp này là tầm thường nếu không phải là vô lý, nhưng thật vô trách nhiệm khi khuyến khích một hành vi như vậy do bảo trì dài hạn và khả năng tiếp cận.

Chỉ cần đi với Apache Commons


7
Tôi đồng ý với các bình luận trước. Bạn không chỉ kéo vào Apache Commons, mà nó còn dễ dàng chuyển thành một tập hợp lớn các phụ thuộc bắc cầu cũng cần được kéo vào. Gần đây tôi có thể loại bỏ một số phụ thuộc đáng kinh ngạc bằng cách thay thế một dòng mã :-( Phụ thuộc rất tốn kém và Viết mã cơ bản như thế này là một thực hành tốt
Peter Kriens

1
Đồng ý với @PeterKriens. Nếu bất cứ điều gì, lỗi là ở Java vì không hỗ trợ các chuyển đổi đơn giản như thế này trong các kiểu dữ liệu tiêu chuẩn của nó
Adam Hughes

3

Nếu bạn đang sử dụng Bộ sưu tập Eclipse , bạn có thể sử dụng collectInt()phương thức để chuyển từ bộ chứa đối tượng sang bộ chứa int nguyên thủy.

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

Nếu bạn có thể chuyển đổi ArrayListthành a FastList, bạn có thể thoát khỏi bộ chuyển đổi.

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

Lưu ý: Tôi là người chuyển đổi cho các bộ sưu tập Eclipse.


3

Java 8:

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

2

Mảng.set ALL ()

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

Đầu ra:

Mảng ints nguyên thủy: [7, 9, 13]

Các công trình tương tự cho một mảng của longhay double, nhưng không phải cho mảng của boolean, char, byte, shorthoặc float. Nếu bạn có một danh sách thực sự lớn, thậm chí có một parallelSetAllphương pháp mà bạn có thể sử dụng thay thế.

Đối với tôi điều này là tốt và đủ để tôi không muốn có một thư viện bên ngoài cũng như không sử dụng các luồng cho nó.

Liên kết tài liệu: Arrays.setAll(int[], IntUnaryOperator)


1

Bạn chỉ có thể sao chép nó vào một mảng:

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

Không quá cầu kỳ; nhưng, này, nó hoạt động ...


1

Một giải pháp một dòng rất đơn giản là:

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

0

Đoạn mã này đang làm việc cho tôi, hãy thử điều này:

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

Đáng để đề cập đến ArrayList nên được khai báo như thế này:

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

5
Xin chào chỉ là một lời nhắc nhở nhẹ nhàng rằng OP muốn một mảng nguyên thủy không phải là một mảng Object.
OLIVER.KOO

3
Nguyên thủy int không bao bọc 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());
    }

1
Câu trả lời này không hoạt động, nó trả về một mảng với một phần tử thay vì nhiều phần tử.
Bí ẩn

Tại sao nên sử dụng StringBuffer? Tại sao lại chuyển đổi Số nguyên thành Chuỗi và sau đó thành Số nguyên rồi chuyển sang số nguyên rồi lại thành Số nguyên? Tại sao sử dụng một mảng có một phần tử trong đó và tại sao lặp lại mảng phần tử đơn đó khi nó chỉ chứa một phần tử? Tại sao truyền các số nguyên cho các đối tượng trong vòng lặp bên ngoài? Có rất nhiều câu hỏi ở đây. Có phải @CodeMadness chỉ là một tài khoản troll?
Victor Zamanian

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

truy cập arrnhư bình thường int[].


5
Điều này không trả lời câu hỏi, câu hỏi là về việc chuyển đổi sang loại nguyên thủy (int)
Asaf
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.