java - Kotlin 中的 ByteArray 到 DoubleArray
问题描述
我想将一个字节数组外推为一个双精度数组。
我知道如何在 Java 中做到这一点。但是 AS 转换器不适用于此... :-D
这是我想用 Kotlin 编写的课程:
class ByteArrayToDoubleArrayConverter {
public double[] invoke(byte[] bytes) {
double[] doubles = new double[bytes.length / 2];
int i = 0;
for (int n = 0; n < bytes.length; n = n + 2) {
doubles[i] = (bytes[n] & 0xFF) | (bytes[n + 1] << 8);
i = i + 1;
}
return doubles;
}
}
这将是预期结果的典型示例:
class ByteArrayToDoubleArrayConverterTest {
@Test
fun `check typical values`() {
val bufferSize = 8
val bytes = ByteArray(bufferSize)
bytes[0] = 1
bytes[1] = 0
bytes[2] = 0
bytes[3] = 1
bytes[4] = 0
bytes[5] = 2
bytes[6] = 1
bytes[7] = 1
val doubles = ByteArrayToDoubleArrayConverter().invoke(bytes)
assertTrue(1.0 == doubles[0])
assertTrue(256.0 == doubles[1])
assertTrue(512.0 == doubles[2])
assertTrue(257.0 == doubles[3])
}
}
任何想法?谢谢!!!
解决方案
我认为使用辅助功能会最清楚。这是一个使用 lambda 将字节对转换为 DoubleArray 的扩展函数:
inline fun ByteArray.mapPairsToDoubles(block: (Byte, Byte) -> Double)
= DoubleArray(size / 2){ i -> block(this[2 * i], this[2 * i + 1]) }
这使用了 DoubleArray 构造函数,该构造函数接受初始化 lambda 和大小,因此您无需在构造后循环设置值。
然后,所需的函数只需要知道如何将每对字节转换为双精度。虽然它作为扩展函数而不是类会更惯用:
fun ByteArray.toDoubleSamples() = mapPairsToDoubles{ a, b ->
(a.toInt() and 0xFF or (b.toInt() shl 8)).toDouble()
}
然后你可以用例如调用它:
bytes.toDoubleSamples()
(.toXxx()
是返回对象的转换版本的函数的常规名称。这种函数的标准名称是toDoubleArray()
,但通常会将每个值转换为自己的双精度值;您正在做的事情更专业,所以更专业的名称会避免混淆。)
那里唯一尴尬的事情(以及从 Java 直接转换失败的原因)是 Kotlin 对其数字类型更加挑剔,并且不会像 Java 和 C 那样自动提升它们;它的位运算符也没有字节重载。因此,您需要在调用andtoInt()
之前显式调用每个字节,然后调用结果。and
shl
toDouble()
结果是代码更短,希望更具可读性,而且非常高效!(没有中间数组或列表,而且——多亏了inline
——甚至没有任何不必要的函数调用。)
(它比大多数 Kotlin 代码更尴尬,因为原始数组不像基于引用的数组那样得到很好的支持——它们本身不像列表那样得到很好的支持。这主要是出于与 Java 兼容性有关的遗留原因。但遗憾的是,没有chunked()
实现 ByteArray,它本可以避免使用辅助函数,尽管代价是临时列表。)
推荐阅读
- html - 在 django 中使用标志作为语言的选项
- python - 如何在 Python 代码中添加 1 级日志详细程度?
- java - Spring WebFlux - 为什么我必须等待 WebClient 响应?
- javascript - Javascript在for循环中返回对象嗨伙计
- amazon-web-services - 在 AWS Lambda 上使用 Python 从 S3 中的 AWS SES 邮件中提取电子邮件附件
- java - 填充对象数组时出现问题。结果始终为空
- php - “将 [name] 添加到可填充属性以允许对 [Illuminate\Foundation\Auth\User] 进行批量分配。”
- ejb - 使用 EJB 应用程序实现微配置文件健康检查
- loops - 批处理 – Findstr 错误级别条件,引号?
- discord - 如果消息包含某些内容,则添加反应