วิธีการหลีกเลี่ยงการทำซ้ำของรหัสที่เกี่ยวกับประเภทดั้งเดิม?


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)ความสัมพันธ์เหล่านี้เป็นปัจจัยสำคัญของปัญหา

คำถาม

ถ้าการทำสำเนาถูกกำจัดได้อย่างไรโดยไม่กระทบต่อประสิทธิภาพการทำงานที่สำคัญ (เช่นโดยการล็อกอัตโนมัติ)

ที่เกี่ยวข้อง


6
ไม่ไม่สามารถทำอะไรได้ การทำสำเนาเป็นตัวเลือกเดียว
Andy Turner

ใช้คอลเล็กชันดั้งเดิมของบุคคลที่สาม
Vince Emigh

1
Java lacks generics on primitive types, so perhaps the repetition is unavoidable.ได้. (โดยทั่วไปจะไม่เป็นปัญหามากนักเนื่องจากเป็นเรื่องยากที่โปรแกรมหนึ่งต้องการมากกว่าหนึ่งตัวที่ต่างกันคุณสามารถ "แก้ไข" สิ่งนี้ได้ด้วยการใส่คำสั่งดั้งเดิมเข้าไปในคลาสและใช้การเรียงลำดับวัตถุแม้ว่ามันจะค่อนข้างช้า )
markspace

3
นอกจากนี้ (โปรดจำไว้ว่านี่) หากคุณกำลังอ่านแบบดั้งเดิมจำนวนมากเช่นรหัสของคุณดูเหมือนว่าใช้ByteBufferวิธีเช่นasDoubleBuffer()หรือasShortBuffer()จะลดการทำงานระดับต่ำสุดบางอย่าง docs.oracle.com/th/java/javase/11/docs/api/java.base/java/nio/ ......
markspace

1
โปรดทราบว่ามีความพยายามบางอย่างที่จะนำการสนับสนุนทั่วไปแบบดั้งเดิมมาสู่ Java เช่นList<int>ฯลฯ วางจำหน่ายในอีก 2-5 ปีหรือมากกว่านั้น มันเรียกว่า Project Valhalla
Zabuzard

คำตอบ:


2

หากคุณกำลังอ่านข้อมูลเบื้องต้นอย่างเช่นรหัสของคุณดูเหมือนว่าจะบ่งบอกว่าใช้ByteBufferเช่นasDoubleBuffer ()หรือasShortBuffer ()จะ offload บางส่วนของการทำงานในระดับต่ำสุด

ตัวอย่าง:

   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`
   }

(คอมไพล์รหัส แต่ไม่ได้ทดสอบ!)


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

การทำซ้ำได้รับการจัดการด้วยค่าใช้จ่ายของประสิทธิภาพการทำงานบางอย่างขาดความปลอดภัยประเภทเวลารวบรวมเล็กน้อยและการใช้การสะท้อนกลับ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.