Chuyển đổi một mảng đối tượng thành một mảng có kiểu nguyên thủy của chúng


80

Nếu bạn có một mảng các đối tượng Java có kiểu nguyên thủy (ví dụ: Byte, Integer, Char, v.v.). Có cách nào gọn gàng để tôi có thể chuyển đổi nó thành một mảng của kiểu nguyên thủy không? Đặc biệt, điều này có thể được thực hiện mà không cần phải tạo một mảng mới và lặp qua nội dung.

Vì vậy, ví dụ, cho

Integer[] array

cách gọn gàng nhất để chuyển nó thành

int[] intArray

Thật không may, đây là điều chúng tôi phải làm khá thường xuyên khi giao tiếp giữa Hibernate và một số thư viện của bên thứ ba mà chúng tôi không kiểm soát được. Có vẻ như đây sẽ là một thao tác khá phổ biến nên tôi sẽ rất ngạc nhiên nếu không có phím tắt.

Cảm ơn bạn đã giúp đỡ!

Câu trả lời:


40

Thật không may, không có gì trong nền tảng Java làm được điều này. Btw, bạn cũng cần phải xử lý rõ ràng nullcác phần tử trong Integer[]mảng ( intbạn sẽ sử dụng những gì cho những phần tử đó?).


6
Điểm tốt về nulls. Đối với mục đích của tôi, tôi đã chấp nhận một ngoại lệ được ném nếu một trong các mục nhập là null, giống như cách NullPointerException được ném khi bạn mở hộp một đối tượng.
Il-Bhima

2
Câu trả lời này không còn chính xác với Java 8, hãy xem câu trả lời của Alex .
robinst


69

Với các luồng được giới thiệu trong Java 8, điều này có thể được thực hiện:

int[] intArray = Arrays.stream(array).mapToInt(Integer::intValue).toArray();

Tuy nhiên, hiện nay có dòng chỉ nguyên thủy cho int, longdouble. Nếu bạn cần chuyển đổi sang kiểu nguyên thủy khác, chẳng hạn như bytecách ngắn nhất mà không có thư viện bên ngoài là:

byte[] byteArray = new byte[array.length];
for(int i = 0; i < array.length; i++) byteArray[i] = array[i];

Hoặc vòng lặp for có thể được thay thế bằng một luồng nếu bạn muốn:

IntStream.range(0, array.length).forEach(i -> byteArray[i] = array[i]);

Tất cả những thứ này sẽ ném ra NullPointerExceptionnếu có bất kỳ phần tử nào của bạn null.


2
Thay vào đó Integer::intValue, bạn cũng có thể sử dụng i -> i(sử dụng tính năng mở hộp).
robinst

1
@robinst Và unboxing là trình biên dịch đang gọi Integer::intValuecho bạn, vậy tại sao phải tạo một lambda mới, khi phương thức này đã có sẵn?
Andreas

@Andreas Chỉ cần liệt kê một tùy chọn khác, tùy chọn bạn chọn là một câu hỏi về kiểu mã / sở thích cá nhân. Tôi cũng đã đánh dấu microbenchmark (sử dụng JMH) hai cách tiếp cận và chúng có cùng hiệu suất.
robinst

Việc sử dụng đoạn mã đầu tiên được đăng đã khiến tôi gặp lỗi "Không thể sử dụng phương thức không tĩnh trong ngữ cảnh tĩnh" nên thay vào đó tôi đã làm như vậy: int[] ints = Arrays.stream(objects).mapToInt(i -> Integer.parseInt(i.toString())).toArray(); Hy vọng điều này sẽ hữu ích cho bất kỳ ai có cùng vấn đề. Và nếu ai biết cách tốt hơn xin vui lòng cho tôi biết.
Kartik Chugh

Đây nên là câu trả lời được chấp nhận ngày nay. Cảm ơn Alex.
Per Lundberg


3

Đặc biệt, điều này có thể được thực hiện mà không cần phải tạo một mảng mới và lặp qua nội dung.

Bạn không thể chuyển đổi mảng Integer thành int (tức là bạn không thể thay đổi kiểu của các phần tử của mảng) trong Java. Vì vậy, bạn phải tạo một mảng int [] mới và sao chép giá trị của các đối tượng Integer vào đó hoặc bạn có thể sử dụng bộ điều hợp:

class IntAdapter {
    private Integer[] array;
    public IntAdapter (Integer[] array) { this.array = array; }
    public int get (int index) { return array[index].intValue(); }
}

Điều này có thể làm cho mã của bạn dễ đọc hơn một chút và đối tượng IntAdapter sẽ chỉ sử dụng một vài byte bộ nhớ. Lợi thế lớn của bộ điều hợp là bạn có thể xử lý các trường hợp đặc biệt ở đây:

class IntAdapter {
    private Integer[] array;
    public int nullValue = 0;
    public IntAdapter (Integer[] array) { this.array = array; }
    public int get (int index) { 
        return array[index] == null ? nullValue : array[index].intValue();
    }
}

Một giải pháp khác là sử dụng Commons Primainst chứa rất nhiều bộ điều hợp được xác định trước. Trong trường hợp của bạn, hãy xem ListIntList .


2

Hoặc chỉ làm theo cách dễ dàng nếu bạn chỉ làm một lần. Nhưng bạn chưa nói về Integer! = Null case.

    //array is the Integer array
    int[] array2 = new int[array.length];
    int i=0;
    for (Integer integer : array) {
        array2[i] = integer.intValue();
        i++;
    }

1

sử dụng Dollar đơn giản như:

Integer[] array = ...;
int[] primitiveArray = $(array).toIntArray();

6
Đây có vẻ không phải là Java, ít nhất không phải là Java 1.6 hoặc 1.7.
Lordalcol

2
@LorDalCol Dollar thực sự là một thư viện Java
Jaroslav Záruba

1
Có thể đặt tên cho một phương thức Java $! Tôi không nghĩ nó được khuyến khích, mặc dù…
Ole VV
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.