English 中文(简体)
将对象数组转换为其原始类型的数组
原标题:
  • 时间:2009-02-19 08:26:50
  •  标签:

如果你有一个Java对象的数组,它们具有原始类型(例如Byte、Integer、Char等),那么是否有一种简便的方法可以将它转换为原始类型的数组呢?尤其是是否可以在不创建新数组并循环遍历内容的情况下完成这个操作?

那么例如,给定

Integer[] array

什么是将这个转换为最简洁的方法?

int[] intArray

不幸的是,当我们在Hibernate和一些我们无法控制的第三方库之间进行接口时,这是我们经常要做的事情。这似乎是一个非常常见的操作,所以如果没有捷径,我会感到惊讶。

谢谢你的帮助!

最佳回答

遗憾的是,Java平台中没有任何东西可以做到这一点。另外,你还需要明确处理数组中的null元素(你会使用什么int代替它们?)。

问题回答

再一次,Apache Commons Lang 是你的好朋友。他们提供了ArrayUtils.toPrimitive(),该方法正好可以满足你的需求。你可以指定如何处理null值。

使用Java 8中引入的流,可以完成此操作:

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

然而,目前仅有intlongdouble的原始流。如果您需要将其转换为另一种原始类型,例如byte,则不使用外部库的最短方式是:

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

如果您想的话,for循环也可以用流来替换:

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

如果您的任何元素为null,所有这些都会抛出NullPointerException

使用Guava:

int[] intArray = Ints.toArray(Arrays.asList(array));

文档记录:

特别是,是否可以在不创建新数组并循环遍历内容的情况下完成此操作。

你不能将一个整数数组转换为 int(即不能更改数组元素的类型)在Java中。因此,你必须创建一个新的 int [] 数组,并将 Integer 对象的值复制到其中,或者你可以使用适配器:

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

这可以使您的代码更易读,而IntAdapter对象仅占用几个字节的内存。适配器的重要优势是您可以在此处处理特殊情况:

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

另一个解决方案是使用Commons Primitives,其中包含许多预定义的适配器。在您的情况下,请查看ListIntList

如果你只想做一次,那就用简单的方法去做。但是你还没有谈到整数!= null的情况。

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

使用Dollar很简单:

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

这里提供了适用于所有基本类型的通用解决方案。

/**
 * Convert Collection to equivalent array of primitive type
 * @param <S> [in] Object type of source collection
 * @param tcls [in] class of the primitive element
 * @param q [in] source collection
 * @return Equivalent Array of tcls-elements, requires cast to "tcls"[]
 */
public static <S> Object asPrimitiveArray(Class<?> tcls, Collection<S> q)
{
    int n = q.size();
    Object res = Array.newInstance(tcls, n);
    Iterator<S> i = q.iterator();
    int j = 0;
    while (i.hasNext())
    {
        Array.set(res, j++, i.next());
    }
    return res;
}

/**
 * Convert Object array to equivalent array of primitive type
 * @param <S> [in] Object type of source array
 * @param tcls [in] class of the primitive element
 * @param s [in] source array
 * @return Equivalent Array of tcls-elements, requires cast to "tcls"[]
 */
public static <S> Object asPrimitiveArray(Class<?> tcls, S[] s)
{
    return asPrimitiveArray(tcls, Arrays.asList(s));
} 

整数到整型的转换

Integer[] a = ...
int[] t = (int[]) asPrimitiveArray(int.class, a);

我们可以使用Stream API从包装对象的对应项创建原始类型数组。

Character[]数组转换为char[],使用相应大小分配的自定义CollectorSupplier<CharBuffer>BiConsumer<CharBuffer, Character>累加器、BinaryOperator<CharBuffer>合并器和Function<CharBuffer,char[]>完成器),如下操作即可:

Collector<Character, CharBuffer, char[]> charArrayCollector = Collector.of(
  () -> CharBuffer.allocate(95), 
  CharBuffer::put, 
  CharBuffer::put, 
  CharBuffer::array
);

它为可打印ASCII字符提供CharBuffer,将每个流式字符累积到CharBuffer实例中,以正确顺序组合来自多个CharBuffer实例的并行处理结果,最终从累积和组合的结果中构建所需的char[]数组,待所有线程完成后。

首先,我们通过利用IntStream中的int值从标准可打印ASCII字符集中迭代ASCII范围,并将每个值映射到Character Stream来创建一个Character[]测试数组。在将它们转换为char原语并将其转换为Character对象之后:

Character[] asciiCharacters = IntStream.range(32, 127)
  .mapToObj(i -> Character.valueOf((char)i))
  .toArray(Character[]::new);

现在,我们只需要从数组创建字符的,然后通过自定义收集器收集到数组中。

char[] asciiChars = Stream.of(asciiCharacters ).collect(charArrayCollector);

这同样适用于其他Number类型:

byte[] bytes = new byte[] { Byte.MIN_VALUE, -1 , 0, 1, Byte.MAX_VALUE };
Byte[] boxedBytes = IntStream.range(0, bytes.length)
  .mapToObj(i -> bytes[i])
  .toArray(Byte[]::new);
byte[] collectedBytes = Stream.of(boxedBytes).collect(
  Collector.of(
    () -> ByteBuffer.allocate(boxedBytes.length), 
    ByteBuffer::put, 
    ByteBuffer::put, 
    ByteBuffer::array
  )
);

short[] shorts = new short[] { Short.MIN_VALUE, -1, 0, 1, Short.MAX_VALUE };
Short[] boxedShorts = IntStream.range(0, shorts.length)
  .mapToObj(i -> shorts[i])
  .toArray(Short[]::new);
short[] collectedShorts = Stream.of(boxedShorts).collect(
  Collector.of(
    () -> ShortBuffer.allocate(boxedShorts .length), 
    ShortBuffer::put, 
    ShortBuffer::put, 
    ShortBuffer::array
  )
);

float[] floats = new float[] { Float.MIN_VALUE, -1.0f, 0f, 1.0f, Float.MAX_VALUE };
Float[] boxedFLoats = IntStream.range(0, floats.length)
  .mapToObj(i -> floats[i])
  .toArray(Float[]::new);
float[] collectedFloats = Stream.of(boxedFLoats).collect(
  Collector.of(
    () -> FloatBuffer.allocate(boxedFLoats.length), 
    FloatBuffer::put, 
    FloatBuffer::put, 
    FloatBuffer::array
  )
);

原始类型,Stream API 支持它,可以更容易地进行转换:

int[] ints = new int[] { Integer.MIN_VALUE, -1, 0, 1, Integer.MAX_VALUE };
Integer[] integers = IntStream.of(ints).boxed().toArray(Integer[]::new);
int[] collectedInts = Stream.of(integers).collect(
  Collector.of(
    () -> IntBuffer.allocate(integers.length), 
    IntBuffer::put, 
    IntBuffer::put, 
    IntBuffer::array
  )
);

long[] longs = new long[] { Long.MIN_VALUE, -1l, 0l, 1l, Long.MAX_VALUE };
Long[] boxedLongs = LongStream.of(longs).boxed().toArray(Long[]::new);
long[] collectedLongs = Stream.of(boxedLongs ).collect(
  Collector.of(
    () -> LongBuffer.allocate(boxedLongs .length), 
    LongBuffer::put, 
    LongBuffer::put, 
    LongBuffer::array
  )
);

double[] doubles = new double[] { Double.MIN_VALUE, -1.0, 0, 1.0, Double.MAX_VALUE };
Double[] boxedDoubles = DoubleStream.of(doubles)
  .boxed()
  .toArray(Double[]::new);
double[] collectedDoubles = Stream.of(boxedDoubles).collect(
  Collector.of(
    () -> DoubleBuffer.allocate(boxedDoubles.length), 
    DoubleBuffer::put, 
    DoubleBuffer::put, 
    DoubleBuffer::array
  )
);

Yes, we can convert Arrays of Objects to primitive, please refer below code. Java 8 is awesome at to learn java 8 skills in more detail I have got one youtube channel.

https://www.youtube.com/@thefullstackguy Happy Learning :)

private static int[] reverseJava8(int[] arr) {
    Object[] objects = Arrays.stream(arr)
            .boxed()
            .sorted(Comparator.reverseOrder())
            .toArray();
    return Arrays.stream(objects).mapToInt(i -> (int) i).toArray();

}




相关问题
热门标签