我正在移植一些Objective C代码。
我需要创建一个列表(我将使用任何类型的列表,无论有意义)对象。该课程如下:
class Foo{
double fooValue1;
double fooValue2;
double fooValue3;
double fooValue4;
}
我正在将二进制文件读入字节数组,该数组工作正常。字节数组是一个列表 4次双打。因此,如果文件中有100个Foo实例,则字节数组有3200个字节。即4 * 8 * 100。
在Objective C中,变量被声明为指向Foo类型数组的指针。通过简单地复制字节来加载该数组是非常快的。这样做的陈述是:
[byteArray getBytes:fooData range:range]
其中range是NSRange
实例,其中location = 0,length =字节数组的长度,byteArray是从文件读取的原始byte [],fooData是指向目标数组的指针。
目前,我循环遍历字节数组,为每32个字节创建一个新的Foo实例,然后通过将每个8字节转换为双精度来分配字段。对于数千个对象,这很慢。
我的目标是API 8,因此我无法使用Arrays.copyOf
,但如果它提供了一个很好的解决方案,我会考虑更改目标。
问题是;有没有办法以与Objective C类似的“一种语句”方式创建列表?
由于
[编辑]这是我根据彼得的答案使用的最终代码。我应该补充说,该文件实际上包含一个列表,用标题分隔。解析文件的结果是一个字节数组的数组。
ArrayList<SCGisPointData> pointData = new ArrayList<SCGisPointData>();
SCGisPointData thisPointdata;
for (byte[] ring : linearRings) {
DoubleBuffer buffer = ByteBuffer.wrap(ring).order(ByteOrder.nativeOrder()).asDoubleBuffer().asReadOnlyBuffer();
thisPointdata= new SCGisPointData ();
while (buffer.hasRemaining()) {
thisPointdata = new SCGisPointData();
thisPointdata.longitude = buffer.get();
thisPointdata.latitude = buffer.get();
thisPointdata.sinLatitude = buffer.get();
thisPointdata.cosLatitude = buffer.get();
pointData.add(thisPointdata);
}
}
答案 0 :(得分:2)
纯Java中没有办法神奇地假设一种类型可以变成另一种类型。 BTW您可以使用Unsafe在HotSpot中执行此操作,但我不相信您可以在Android中使用它,这可能是最好的。
您可以使用带有本机字节顺序的直接ByteBuffer来加速转换。这样可以最大限度地降低开销,但在Android中并不像在HotSpot中那么快(因为后者可以将这些转化为内在方法)
我想花多长时间作为估计
// or use a MappedByteBuffer from a file
ByteBuffer bb = ByteBuffer.allocateDirect(3200).order(ByteOrder.nativeOrder());
while(bb.remaining() > 0) {
float f= bb.getFloat();
}
注意:这将无法运行足够长的时间甚至可以JIT到本机代码。
ByteBuffer bb = ByteBuffer.allocateDirect(3200).order(ByteOrder.nativeOrder());
for (int i = 0; i < 12; i++) {
long start = System.nanoTime();
bb.clear(); // simulate we have 3200 bytes to read.
int count = 0;
while (bb.remaining() > 0) {
float f = bb.getFloat();
count++;
}
long time = System.nanoTime() - start;
System.out.printf("Took %,d micro-seconds to read %,d float values%n", time / 1000, count);
}
on HotSpot Java 7打印
Took 960 micro-seconds to read 800 float values
Took 141 micro-seconds to read 800 float values
Took 99 micro-seconds to read 800 float values
Took 101 micro-seconds to read 800 float values
Took 100 micro-seconds to read 800 float values
Took 102 micro-seconds to read 800 float values
Took 115 micro-seconds to read 800 float values
Took 127 micro-seconds to read 800 float values
Took 108 micro-seconds to read 800 float values
Took 79 micro-seconds to read 800 float values
Took 78 micro-seconds to read 800 float values
Took 79 micro-seconds to read 800 float values
答案 1 :(得分:1)
看看MappedByteBuffer。可在Android上使用,并允许您:
您必须小心选择正确的字句。下面是一些示例代码(请注意,API会将字节缓冲区“转换”为双缓冲区,并且您可以一次性从缓冲区中检索多个双精度段):
final String fileName = "/some/path/data.txt";
final MappedByteBuffer byteBuffer = new FileInputStream(fileName)
.getChannel()
.map(MapMode.READ_ONLY, 0, 3200);
final DoubleBuffer doubleBuffer = byteBuffer.asDoubleBuffer();
double[] swap = new double[4];
doubleBuffer.get(swap);