Konwersja tablicy obiektów na tablicę ich typów pierwotnych


80

Jeśli masz tablicę obiektów Java, które mają typ pierwotny (na przykład Byte, Integer, Char itp.). Czy istnieje zgrabny sposób na przekształcenie go w tablicę typu pierwotnego? W szczególności można to zrobić bez konieczności tworzenia nowej tablicy i przeglądania zawartości w pętli.

Na przykład dane

Integer[] array

jaki jest najładniejszy sposób przekształcenia tego w

int[] intArray

Niestety jest to coś, co musimy robić dość często, gdy łączymy się między Hibernate a niektórymi bibliotekami stron trzecich, nad którymi nie mamy kontroli. Wygląda na to, że byłaby to dość powszechna operacja, więc byłbym zaskoczony, gdyby nie było skrótu.

Dzięki za pomoc!

Odpowiedzi:


40

Niestety na platformie Java nie ma nic, co to robi. Przy okazji, musisz również jawnie obsługiwać nullelementy w Integer[]tablicy (czego intzamierzasz użyć do tego?).


6
Dobra uwaga na temat wartości zerowych. Dla moich celów zaakceptowałbym wyrzucenie wyjątku, jeśli jeden z wpisów ma wartość null, w taki sam sposób, w jaki NullPointerException jest generowany podczas rozpakowywania obiektu.
Il-Bhima,

2
Ta odpowiedź nie jest już dokładna w przypadku języka Java 8, zobacz odpowiedź Alexa .
robinst


70

W przypadku strumieni wprowadzonych w Javie 8 można to zrobić:

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

Jednakże, istnieje obecnie tylko dla prymitywnych strumienie int, longi double. Jeśli chcesz przekonwertować na inny typ pierwotny, taki jak bytenajkrótszy sposób bez zewnętrznej biblioteki, to:

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

Jeśli chcesz, pętlę for można zastąpić strumieniem:

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

Wszystkie te rzucą, NullPointerExceptionjeśli którykolwiek z twoich elementów null.


2
Zamiast tego Integer::intValuemożesz również użyć i -> i(który używa rozpakowywania).
robinst

1
@robinst A rozpakowywanie jest wołaniem kompilatora Integer::intValue, więc po co tworzyć nową lambdę, skoro metoda jest łatwo dostępna?
Andreas

@Andreas Wystarczy wymienić inną opcję, którą wybierzesz, jest kwestią stylu kodu / osobistych preferencji. Również oznaczyłem (używając JMH) mikroznakowanie obu podejść i mają one taką samą wydajność.
robinst

Użycie pierwszego opublikowanego fragmentu kodu dawało mi błąd „Nie można użyć metody statycznej w kontekście statycznym”, więc zamiast tego zrobiłem: int[] ints = Arrays.stream(objects).mapToInt(i -> Integer.parseInt(i.toString())).toArray(); Mam nadzieję, że jest to pomocne dla każdego, kto ma ten sam problem. A jeśli ktoś zna lepszy sposób, daj mi znać.
Kartik Chugh,

To powinna być obecnie akceptowana odpowiedź. Dzięki Alex.
Per Lundberg


3

W szczególności można to zrobić bez konieczności tworzenia nowej tablicy i przeglądania zawartości w pętli.

Nie możesz przekonwertować tablicy typu Integer na int (tj. Nie możesz zmienić typu elementów tablicy) w Javie. Więc albo musisz utworzyć nową tablicę int [] i skopiować do niej wartość obiektów Integer, albo możesz użyć adaptera:

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

Może to uczynić twój kod bardziej czytelnym, a obiekt IntAdapter będzie zużywał tylko kilka bajtów pamięci. Dużą zaletą adaptera jest to, że poradzisz sobie tutaj ze specjalnymi przypadkami:

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

Innym rozwiązaniem jest użycie Commons Primitives, który zawiera wiele predefiniowanych adapterów. W twoim przypadku spójrz na ListIntList .


2

Lub po prostu zrób to w łatwy sposób, jeśli chcesz to zrobić tylko raz. Ale nie rozmawiałeś o 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

korzystanie z dolara jest proste, jak:

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

6
To nie wydaje się być Java, przynajmniej nie Java 1.6 lub 1.7.
Lordalcol

2
@LorDalCol Dollar jest właściwie biblioteką Java
Jaroslav Záruba

1
Możliwe jest nazwanie metody Java $! Nie wydaje mi się jednak, żeby to było zachęcane…
Ole VV
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.