9

背景

位输入流由字节数组支持。有一些方法可以从该字节数组中读取到各种强制原始数组中。

问题

有重复的代码。Java 缺乏原始类型的泛型,因此重复可能是不可避免的。

代码

重复代码在以下方法中很明显:

@Override
public long readBytes(final byte[] out, final int offset, final int count, final int bits) {
    final int total = offset + count;

    assert out != null;
    assert total <= out.length;

    final long startPosition = position();

    for (int i = offset; i < total; i++) {
        out[i] = readByte(bits);
    }

    return position() - startPosition;
}

@Override
public long readShorts(final short[] out, final int offset, final int count, final int bits) {
    final int total = offset + count;

    assert out != null;
    assert total <= out.length;

    final long startPosition = position();

    for (int i = offset; i < total; i++) {
        out[i] = readShort(bits);
    }

    return position() - startPosition;
}

请注意如何final byte[] out与 相关readByte(bits)final short[] out相关readShort(bits)。这些关系是问题的症结所在。

问题

怎样才能消除重复,如果有的话,又不会对性能造成重大影响(例如,通过自动装箱)?

有关的

4

2 回答 2

2

如果您正在阅读您的代码似乎表明的批量原语,则使用ByteBuffer方法(如asDoubleBuffer()asShortBuffer() )将卸载一些最低级别的工作。

例子:

   public void readBytes( final byte[] out, final int offset, final int count, final ByteBuffer buffer ) {
      buffer.get( out, offset, count );  // udates ByteBuffer `position` automatically
   }

   public void readShorts( final short[] out, final int offset, final int count, final ByteBuffer buffer ) {
      ShortBuffer sb = buffer.asShortBuffer();
      sb.get( out, offset, count );  // note that `count` reads two bytes for each `short`
   }

(代码编译但未经测试!)

于 2020-02-27T21:37:17.650 回答
0

一种会导致性能损失的可能性是将java.lang.reflect.Array数组视为对象,然后允许在所有读取方法中重用相同的代码。

@FunctionalInterface
public interface BitArrayReader {
    Object read(int bits);
}

private long readPrimitive(
        final Object out, final int offset, final int count, final int bits,
        final BitArrayReader reader) {
    final int total = offset + count;

    assert out != null;
    assert total <= Array.getLength(out);

    final long startPosition = position();

    for (int i = offset; i < total; i++) {
        Array.set(out, i, reader.read(bits));
    }

    return position() - startPosition;
}

@Override
public long readBooleans(boolean[] out, int offset, int count, int bits) {
    return readPrimitive(out, offset, count, bits, this::readBoolean);
}

以牺牲一些性能、轻微缺乏编译时类型安全和使用反射为代价来解决重复问题。

于 2020-03-04T20:11:12.433 回答