Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grab a segment of an array in Java without creating a new array on heap

Tags:

java

arrays

slice

People also ask

How do you substring an array in Java?

To extract a substring as an array of characters in Java, use the getChars() method. Let's say the following is our string and character array. String str = "World is not enough!"; char[] chArr = new char[10]; Now, use the getChars() method to extract a substring.

Is there array slicing in Java?

In Java, array slicing is a way to get a subarray of the given array.


Disclaimer: This answer does not conform to the constraints of the question:

I don't want to have to create a new byte array in the heap memory just to do that.

(Honestly, I feel my answer is worthy of deletion. The answer by @unique72 is correct. Imma let this edit sit for a bit and then I shall delete this answer.)


I don't know of a way to do this directly with arrays without additional heap allocation, but the other answers using a sub-list wrapper have additional allocation for the wrapper only – but not the array – which would be useful in the case of a large array.

That said, if one is looking for brevity, the utility method Arrays.copyOfRange() was introduced in Java 6 (late 2006?):

byte [] a = new byte [] {0, 1, 2, 3, 4, 5, 6, 7};

// get a[4], a[5]

byte [] subArray = Arrays.copyOfRange(a, 4, 6);

Arrays.asList(myArray) delegates to new ArrayList(myArray), which doesn't copy the array but just stores the reference. Using List.subList(start, end) after that makes a SubList which just references the original list (which still just references the array). No copying of the array or its contents, just wrapper creation, and all lists involved are backed by the original array. (I thought it'd be heavier.)


If you're seeking a pointer style aliasing approach, so that you don't even need to allocate space and copy the data then I believe you're out of luck.

System.arraycopy() will copy from your source to destination, and efficiency is claimed for this utility. You do need to allocate the destination array.


One way is to wrap the array in java.nio.ByteBuffer, use the absolute put/get functions, and slice the buffer to work on a subarray.

For instance:

doSomething(ByteBuffer twoBytes) {
    byte b1 = twoBytes.get(0);
    byte b2 = twoBytes.get(1);
    ...
}

void someMethod(byte[] bigArray) {
      int offset = 4;
      int length = 2;
      doSomething(ByteBuffer.wrap(bigArray, offset, length).slice());
}

Note that you have to call both wrap() and slice(), since wrap() by itself only affects the relative put/get functions, not the absolute ones.

ByteBuffer can be a bit tricky to understand, but is most likely efficiently implemented, and well worth learning.


Use java.nio.Buffer's. It's a lightweight wrapper for buffers of various primitive types and helps manage slicing, position, conversion, byte ordering, etc.

If your bytes originate from a Stream, the NIO Buffers can use "direct mode" which creates a buffer backed by native resources. This can improve performance in a lot of cases.