Converting Array of Primitives to Array of Containers in Java

Is there an elegant way to turn an array of primitives into an array of the corresponding container objects -- turn a byte[] into a Byte[], for example? Or am I stuck with looping through it and doing it manually?

Yeah, the for loop isn't exactly difficult. Just kinda ugly.


Apache Commons

Apache Commons / Lang has a class ArrayUtils that defines these methods.

  • All methods called toObject(...) convert from primitive array to wrapper array
  • All called toPrimitive(...) convert from wrapper object array to primitive array

Example:

final int[]     original        = new int[] { 1, 2, 3 };
final Integer[] wrappers        = ArrayUtils.toObject(original);
final int[]     primitivesAgain = ArrayUtils.toPrimitive(wrappers);
assert Arrays.equals(original, primitivesAgain);

Guava

But then I'd say that Arrays of wrapped primitives are not very useful, so you might want to have a look at Guava instead, which provides Lists of all numeric types, backed by primitive arrays:

List<Integer> intList = Ints.asList(1,2,3,4,5);
List<Long> longList   = Longs.asList(1L,2L,3L,4L,5L);
// etc.

The nice think about these array-backed collections is that

  1. they are live views (i.e. updates to the array change the list and vice-versa)
  2. the wrapper objects are only created when needed (e.g. when iterating the List)

See: Guava Explained / Primitives


Java 8

On the other hand, with Java 8 lambdas / streams, you can make these conversions pretty simple without using external libraries:

int[] primitiveInts = {1, 2, 3};
Integer[] wrappedInts = Arrays.stream(primitiveInts)
                              .boxed()
                              .toArray(Integer[]::new);
int[] unwrappedInts = Arrays.stream(wrappedInts)
                             .mapToInt(Integer::intValue)
                             .toArray();
assertArrayEquals(primitiveInts, unwrappedInts);

double[] primitiveDoubles = {1.1d, 2.2d, 3.3d};
Double[] wrappedDoubles = Arrays.stream(primitiveDoubles)
                                .boxed()
                                .toArray(Double[]::new);
double[] unwrappedDoubles = Arrays.stream(wrappedDoubles)
                                  .mapToDouble(Double::doubleValue)
                                  .toArray();

assertArrayEquals(primitiveDoubles, unwrappedDoubles, 0.0001d);

Note that the Java 8 version works for int, long and double, but not for byte, as Arrays.stream() only has overloads for int[], long[], double[] or a generic object T[].


You have to loop through your array.


Updated after @seanizer answer :

Basically the toObject(byte[] array) method will do the looping for you :

public static Byte[] toObject(byte[] array) {
    if (array == null) {
        return null;
    } else if (array.length == 0) {
        return EMPTY_BYTE_OBJECT_ARRAY;
    }
    final Byte[] result = new Byte[array.length];
    for (int i = 0; i < array.length; i++) {
        result[i] = new Byte(array[i]);
    }
    return result;
}

And unless you will really use the commons lang lib, you should simply reuse this method and avoid a useless dependency (IMHO).


Just to suggest an alternative, with Guava you can use one of the primitive type utilities such as Bytes or Ints to create a List of the wrapper type:

byte[] bytes = ...
List<Byte> byteList = Bytes.asList(bytes);

Rather than looping through and converting each byte, these methods actually create a list that is backed by the given array. If you really need a Byte[], this obviously doesn't directly give you what you need (though you can get it using .toArray(new Byte[bytes.length]) of course). Collections are vastly superior to arrays for objects, though, and should be preferred when possible.


Here is a short generic way of doing it without using any external libraries and it works for all primitives:

import static java.lang.reflect.Array.*;
import java.util.Arrays;

public class DeepConverter {

  public static void main(String args[]) {        
    long L1[][][] = {{{1,2},{3,4}}, {{5,6}}, {{7}},{{8,9,10,11}}};
    L1 = new long[2][0][7];
    Long L2[][] = (Long[][])box(L1);
    System.out.println(Arrays.deepToString(L2));        
  }

  public static Object box(Object src) {        
    try {
        int length = src.getClass().isArray() ? getLength(src) : 0;        
        if(length == 0)
            return src;        
        Object dest = newInstance(typeCastTo(wrap(get(src, 0))), length);        
        for(int i = 0; i < length; i++)
            set(dest, i, wrap(get(src, i)));        
        return dest;

    } catch(Exception e) {
        throw new ClassCastException("Object to wrap must be an array of primitives with no 0 dimensions");
    }
  }

  private static Class<?> typeCastTo(Object obj) {
    Class<?> type = obj.getClass();
    if(type.equals(boolean.class)) return Boolean.class;
    if(type.equals(byte.class)) return Byte.class;
    if(type.equals(char.class)) return Character.class;
    if(type.equals(double.class)) return Double.class;
    if(type.equals(float.class)) return Float.class;
    if(type.equals(int.class)) return Integer.class;
    if(type.equals(long.class)) return Long.class;
    if(type.equals(short.class)) return Short.class;
    if(type.equals(void.class)) return Void.class;        
    return type;
  }
}