8

String.substring() efficiently reuses the underlying char[] within the String object, I'm wondering if there is an immutable container for byte[] arrays that supports a similar kind of efficient reuse of the underlying array.

Extra points if it can handle things like efficient append and prepend. Still extra points if its packaged for Maven.

Anyone know of such a thing?

sanity
  • 35,347
  • 40
  • 135
  • 226
  • 1
    I have not been able to find anything besides Protocol Buffers ByteString, which is not ideal for use in APIs. I wrote a [blog post](https://fluo.apache.org/blog/2016/11/10/immutable-bytes/) about the need for this in Java, why ByteBuffer is not suitable, and why ByteString is not suitable for APIs. I [asked the openjdk mailing list](http://mail.openjdk.java.net/pipermail/discuss/2016-November/004062.html) about this need and it seemed there was agreement Java does need it, but they wanted to define the bigger story of immutability rather than just add this one class. Someone needs to push for – Keith Turner Dec 14 '16 at 20:18

2 Answers2

4

There's the Protocol Buffers ByteString. From the JavaDoc:

Immutable sequence of bytes. Substring is supported by sharing the reference to the immutable underlying bytes, as with String. Concatenation is likewise supported without copying (long strings) by building a tree of pieces in RopeByteString.

mjanicek
  • 81
  • 1
  • 4
4

The most suitable thing that comes into my mind without going outside base SDK are java.nio Buffers, like ByteBuffer..

Jack
  • 131,802
  • 30
  • 241
  • 343
  • +1 It has the "immutable view", and with `slice` it supports subsequences. The readonly buffer's position and limit can still be modified, though, so you may want to create a wrapper class around it. – Paŭlo Ebermann Mar 29 '11 at 23:34
  • 1
    Can you give me a pointer to the immutable view - I can't find any reference to it? To be honest I was hoping people wouldn't suggest ByteBuffers, I find them a real PITA to work with, very error-prone relative to InputStreams and OutputStreams due to their fundamentally mutable nature :-/ – sanity Mar 29 '11 at 23:36
  • There is `asReadOnlyBuffer()` hidden between `asLongBuffer` and `asShortBuffer`. – Paŭlo Ebermann Mar 29 '11 at 23:56
  • 7
    `asReadOnlyBuffer()` is not immutable. It is read-only. The original consstructor can still modify the buffer. – Gili Oct 03 '11 at 15:32
  • @Gili It's effectively immutable if the original array is no longer accessible. `String`, considered immutable, also just a read-only wrapper over its internal `char[]`. And [there is a hack](https://stackoverflow.com/a/11147102/3948862) for creating a `String` instance with a dirty access to its `char[]`. It's better to consider a readonly buffer not immutable because calling `get()` changes its hashcode. – Dávid Horváth Jan 12 '21 at 03:54
  • @DávidHorváth `String` allocates a `char[]` internally and tries to avoid leaking references to the outside world (the hack you referenced seems like an oversight). If it wasn't for that oversight, it would be unquestionably immutable. NIO buffers are quite different in the sense that anyone can allocate a `char[]` externally, pass it into a `Buffer` and continue to mutate the original array. `Buffer` does nothing to protect against this behavior. Hence, I disagree that `Buffer` is effectively immutable. It is just read-only. – Gili Jan 13 '21 at 04:29