如果您有一个具有基本类型(例如 Byte、Integer、Char 等)的 Java 对象数组。有没有一种巧妙的方法可以将其转换为原始类型的数组?特别是,无需创建新数组并循环内容即可完成此操作。
例如,给定
Integer[] array
将其转换为最巧妙的方法是什么
int[] intArray
不幸的是,这是我们在 Hibernate 和一些我们无法控制的第三方库之间进行交互时必须经常做的事情。看来这是一个很常见的操作,所以如果没有捷径,我会感到惊讶。
感谢您的帮助!
再次强调,Apache Commons Lang 是您的朋友。他们提供了 ArrayUtils.toPrimitive() ,它正是你所需要的。您可以指定如何处理空值。
通过 Java 8 中引入的 streams 可以做到这一点:
int[] intArray = Arrays.stream(array).mapToInt(Integer::intValue).toArray();
但是,目前只有
int
、long
和 double
的原始流。如果您需要转换为另一种原始类型,例如 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]);
如果您的任何元素是
NullPointerException
,所有这些都会抛出 null
。
不幸的是,Java 平台中没有任何东西可以做到这一点。顺便说一句,您还需要显式处理
null
数组中的 Integer[]
元素(您要使用什么 int
来处理这些元素?)。
使用番石榴:
int[] intArray = Ints.toArray(Arrays.asList(array));
文档:
Arrays.asList
(核心API)Ints.toArray
(番石榴)特别是,无需创建新数组并循环内容即可完成此操作。
在 Java 中,您无法将 Integer 数组转换为 int(即您无法更改数组元素的类型)。因此,您必须创建一个新的 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。
或者如果您只想做一次,就用简单的方法来做。但你还没有讨论 Integer!=null 的情况。
//array is the Integer array
int[] array2 = new int[array.length];
int i=0;
for (Integer integer : array) {
array2[i] = integer.intValue();
i++;
}
使用美元很简单:
Integer[] array = ...;
int[] primitiveArray = $(array).toIntArray();
我们可以使用
Stream
API 从盒装对象对应项创建原始类型数组。
对于
Character[]
数组转换为 char[]
,使用相应大小分配的自定义 Collector
,以及 Supplier<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[]
数组,之后所有线程都已完成。
首先,我们从标准可打印 ASCII 集创建一个
Character[]
测试数组,利用 int
中的 IntStream
值,迭代 ASCII 范围并将每个值映射到字符 Stream
,之后将它们转换为 char
原语并将其转换为 Character
对象:
Character[] asciiCharacters = IntStream.range(32, 127)
.mapToObj(i -> Character.valueOf((char)i))
.toArray(Character[]::new);
现在,我们只需从
Stream
数组创建一个 Character
字符,然后可以由自定义收集器将其收集到 char[]
数组中。
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
)
);
是的,我们可以将对象数组转换为原始数组,请参考下面的代码。 Java 8 非常适合更详细地学习 Java 8 技能,我有一个 YouTube 频道。
https://www.youtube.com/@thefullstackguy 快乐学习:)
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();
}
这是所有原始类型的通用解决方案
/**
* Convert Collection to equivalent array of primitive type
* @param <S> [in] Element 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] Element 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));
}
对于整数到 int 的转换
Integer[] a = ...
int[] t = (int[]) asPrimitiveArray(int.class, a);