5

In java, I'm wondering how can I get byte[] of other byte[] from specific position without copying it?

Example:

byte[] bytes1 = new byte[100];
for (int i = 0; i < 100; i++) {
    bytes1[i] = (byte)(i+1);
}
byte[] byte2;

How can I point byte2 to byte1 at position 10? I want that byte2 will have: [0] = 10, [1] = 11, [2] = 12

Is it possible ?

I tried with ByteBuffer but without any success.

Grice
  • 1,345
  • 11
  • 24
user3668129
  • 4,318
  • 6
  • 45
  • 87

3 Answers3

4

The only thing short of screwing with the VM internals (yes, it is possible to do pointer arithmetic with e.g. to-and-fro JNI calls) is using way similar to Arrays.asList(bytes1).subList(startIndex, endIndex) (note that asList() doesn't work with primitive arrays by itself, you'd have to write or find on the 'net a similar implementation for primitives; http://fastutil.di.unimi.it/docs/it/unimi/dsi/fastutil/bytes/ByteList.html#subList%28int comes to mind here) - note that you'll get a List view this way, not byte[], since that'd be essentially impossible in Java (with the exception of VM hacks, mind me).

Alternatively, do what you said - use java.nio.Buffer, ByteBuffer specifically, since that's the Java counterpart of pointer to memory; with array-backed ByteBuffer you can essentially either access the array directly or access the buffer in abstracted/modified (e.g. with offset) way.

ByteBuffer bytes1 = ByteBuffer.allocate(100);
for (int i = 0; i < 100; i++) {
    bytes1.put((byte)(i+1));
}
bytes1.position(offset);
ByteBuffer byte2 = bytes1.slice();

or even

byte[] bytes1 = new byte[100];
for (int i = 0; i < 100; i++) {
    bytes1[i] = (byte)(i+1);
}
ByteBuffer bytes1 = ByteBuffer.wrap(bytes1);
bytes1.position(offset);
ByteBuffer byte2 = bytes1.slice();
  • byte[] bytes = new byte[100]; for (int i = 0; i < 100; i++) { bytes[i] = (byte)(i+1); } ByteBuffer bf1 = ByteBuffer.wrap(bytes); bf1.position(15); ByteBuffer bf2 = bf1.slice(); byte[] byes2 = bf2.array(); but byte2 doesnt contain 15, 16, 17. it does contain 1, 2, 3... so ByteBuffer doesnt help – user3668129 Dec 16 '14 at 03:44
  • 1
    @user3668129 please read both the answer and API docs before stating "something doesn't help"! if you want to use the ByteBuffer with *offset* (`.slice()`), you have to use `get()` or other `ByteBuffer` methods, not `.array()` - the backing array is still the same! That's exactly why I *never* used `array()` in my code and said "with array-backed ByteBuffer you can essentially either access the array directly or access the buffer in abstracted/modified (e.g. with offset) way." direct array access is mutually exclusive with abstracted (offset) access in Java! –  Dec 16 '14 at 10:29
3

Unfortunately, you can't. What you are asking for essentially is C/C++ pointer arithmetic, and there is no such thing in Java.

However, if you are willing to use a different interface, you might have some luck with Commons Primitives ArrayByteList. It's not a simple List<Byte>, as it's backed by a true array of bytes - thus there is no memory overhead due to using Byte objects. You will still have some object overhead, but that's acceptable in practical instances.

Most importantly, it supports slices via the ArrayByteList.subList() method, which does not produce a copy. You can check the source code, the slice is implemented as a reference to the original array plus two markers for begin and end positions.

However, keep in mind that avoiding the copy means that changes to the slice are reflected in the original array. It's probably what you want, but still be very careful - especially if you don't come from a C/C++ background, where these things are common practice.

Dwhitz
  • 1,250
  • 7
  • 26
  • 38
Stefano Sanfilippo
  • 32,265
  • 7
  • 79
  • 80
-1

I'm sorry, you can't.

In java every array is an object. Apart from storing elements, it also stores length of array.

Alexey Shmalko
  • 3,678
  • 1
  • 19
  • 35