在Java中将基元数组转换为容器数组

Bla*_*ppo 46 java arrays

是否有一种优雅的方法将基元数组转换为相应容器对象的数组 - 例如,将a byte[]转换为a Byte[]?还是我坚持循环并手动完成?

是的,for循环并不是很困难.只是有点难看.

Sea*_*oyd 73

Apache Commons

Apache Commons/Lang有一个定义这些方法的ArrayUtils类.

  • 所有方法都称为toObject(...) 从原始数组转换为包装器数组
  • 所有调用都toPrimitive(...)从包装器对象数组转换为原始数组

例:

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);
Run Code Online (Sandbox Code Playgroud)

番石榴

但是后来我会说包裹原语的数组不是很有用,所以你可能想要看一下Guava,它提供所有数字类型的列表,由原始数组支持:

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

好想想这些支持数组的集合就是这样

  1. 它们是实时视图(即对阵列的更新会更改列表,反之亦然)
  2. 包装器对象仅在需要时创建(例如,在迭代List时)

请参阅:番石榴解释/原始


Java 8

另一方面,使用Java 8 lambdas/streams,您可以在不使用外部库的情况下使这些转换变得非常简单:

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);
Run Code Online (Sandbox Code Playgroud)

请注意,在Java 8版本适用int,long并且double,而不是byte作为Arrays.stream()只具有过载int[],long[],double[]或者一个通用的对象T[].

  • Arrays.stream(Byte [])是否过载? (2认同)
  • Java 8 解决方案不适用于发布的问题。`Arrays.stream()` 没有 `byte[]` 的重载 (2认同)

Col*_*ert 8

你必须遍历你的数组.


@seanizer回答后更新:

基本上该toObject(byte[] array)方法将为您循环:

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;
}
Run Code Online (Sandbox Code Playgroud)

除非你真的使用commons lang lib,否则你应该简单地重用这个方法并避免无用的依赖(恕我直言).

  • @Erick我非常不同意.对问题的不同观点很重要 (7认同)
  • 我不认为依赖是无用的.StringUtils.*方法节省了大量时间.ArrayUtils是奖金:-) (4认同)
  • @seanizer我完全同意,Commons lang非常有用,我只是说只有一个静态方法依赖于它不是. (4认同)

Col*_*inD 8

只是建议一个替代方案,使用Guava,您可以使用其中一个基本类型实用程序,例如BytesInts创建List包装器类型:

byte[] bytes = ...
List<Byte> byteList = Bytes.asList(bytes);
Run Code Online (Sandbox Code Playgroud)

byte这些方法实际上创建了一个由给定数组支持的列表,而不是循环并转换每个方法.如果你真的需要一个Byte[],这显然不会直接给你你需要的东西(虽然你.toArray(new Byte[bytes.length])当然可以使用它).但是,集合远远优于对象的数组,并且应尽可能优先使用.

  • 我同意.集合规则,数组吮吸,番石榴规则(+1) (2认同)