@@ -25,7 +25,7 @@ class MultiBuffer implements Buffer {
2525 /** Maximum size per underlying chunk. */
2626 static final int CHUNK_SIZE = Integer .MAX_VALUE / 2 ;
2727
28- final List < ByteBuffer > buffers = new ArrayList <>() ;
28+ final ByteBuffer [] buffers ;
2929 private final long capacity ;
3030
3131 private long position = 0 ;
@@ -46,17 +46,24 @@ public MultiBuffer(long capacity) {
4646
4747 int fullChunks = (int ) (capacity / CHUNK_SIZE );
4848 int remainder = (int ) (capacity % CHUNK_SIZE );
49+ int totalChunks = fullChunks + (remainder > 0 ? 1 : 0 );
50+
51+ this .buffers = new ByteBuffer [totalChunks ];
52+
4953 for (int i = 0 ; i < fullChunks ; i ++) {
50- buffers . add ( ByteBuffer .allocateDirect (CHUNK_SIZE ) );
54+ buffers [ i ] = ByteBuffer .allocateDirect (CHUNK_SIZE );
5155 }
5256 if (remainder > 0 ) {
53- buffers . add ( ByteBuffer .allocateDirect (remainder ) );
57+ buffers [ totalChunks - 1 ] = ByteBuffer .allocateDirect (remainder );
5458 }
5559 }
5660
57- private MultiBuffer (List <ByteBuffer > buffers ) {
58- this .buffers .addAll (buffers );
59- long capacity = buffers .stream ().mapToLong (ByteBuffer ::capacity ).sum ();
61+ private MultiBuffer (ByteBuffer [] buffers ) {
62+ this .buffers = buffers .clone ();
63+ long capacity = 0 ;
64+ for (ByteBuffer buffer : buffers ) {
65+ capacity += buffer .capacity ();
66+ }
6067 this .capacity = capacity ;
6168 this .limit = capacity ;
6269 }
@@ -126,7 +133,7 @@ public Buffer get(byte[] dst) {
126133 while (length > 0 ) {
127134 int bufIndex = (int ) (pos / CHUNK_SIZE );
128135 int bufOffset = (int ) (pos % CHUNK_SIZE );
129- ByteBuffer buf = buffers . get ( bufIndex ) .duplicate ();
136+ ByteBuffer buf = buffers [ bufIndex ] .duplicate ();
130137 buf .position (bufOffset );
131138 int toRead = Math .min (buf .remaining (), length );
132139 buf .get (dst , offset , toRead );
@@ -146,15 +153,15 @@ public byte get(long index) {
146153 }
147154 int bufIndex = (int ) (index / CHUNK_SIZE );
148155 int offset = (int ) (index % CHUNK_SIZE );
149- return buffers . get ( bufIndex ) .get (offset );
156+ return buffers [ bufIndex ] .get (offset );
150157 }
151158
152159 /** {@inheritDoc} */
153160 @ Override
154161 public double getDouble () {
155162 int bufIndex = (int ) (position / CHUNK_SIZE );
156163 int off = (int ) (position % CHUNK_SIZE );
157- ByteBuffer buf = buffers . get ( bufIndex ) ;
164+ ByteBuffer buf = buffers [ bufIndex ] ;
158165 buf .position (off );
159166 if (buf .remaining () >= 8 ) {
160167 double value = buf .getDouble ();
@@ -172,7 +179,7 @@ public double getDouble() {
172179 public float getFloat () {
173180 int bufIndex = (int ) (position / CHUNK_SIZE );
174181 int off = (int ) (position % CHUNK_SIZE );
175- ByteBuffer buf = buffers . get ( bufIndex ) ;
182+ ByteBuffer buf = buffers [ bufIndex ] ;
176183 buf .position (off );
177184 if (buf .remaining () >= 4 ) {
178185 float value = buf .getFloat ();
@@ -189,8 +196,8 @@ public float getFloat() {
189196 @ Override
190197 public Buffer duplicate () {
191198 MultiBuffer copy = new MultiBuffer (capacity );
192- for (int i = 0 ; i < buffers .size () ; i ++) {
193- copy .buffers . set ( i , buffers . get ( i ) .duplicate () );
199+ for (int i = 0 ; i < buffers .length ; i ++) {
200+ copy .buffers [ i ] = buffers [ i ] .duplicate ();
194201 }
195202 copy .position = this .position ;
196203 copy .limit = this .limit ;
@@ -202,8 +209,8 @@ public Buffer duplicate() {
202209 public long readFrom (FileChannel channel ) throws IOException {
203210 long totalRead = 0 ;
204211 long pos = position ;
205- for (int i = (int ) (pos / CHUNK_SIZE ); i < buffers .size () ; i ++) {
206- ByteBuffer buf = buffers . get ( i ) ;
212+ for (int i = (int ) (pos / CHUNK_SIZE ); i < buffers .length ; i ++) {
213+ ByteBuffer buf = buffers [ i ] ;
207214 buf .position ((int ) (pos % CHUNK_SIZE ));
208215 int read = channel .read (buf );
209216 if (read == -1 ) {
@@ -240,7 +247,7 @@ public String decode(CharsetDecoder decoder)
240247 int bufIndex = (int ) (pos / CHUNK_SIZE );
241248 int bufOffset = (int ) (pos % CHUNK_SIZE );
242249
243- ByteBuffer srcView = buffers . get ( bufIndex ) .duplicate ();
250+ ByteBuffer srcView = buffers [ bufIndex ] .duplicate ();
244251 srcView .position (bufOffset );
245252
246253 int toRead = (int ) Math .min (srcView .remaining (), remainingBytes );
@@ -272,13 +279,13 @@ public String decode(CharsetDecoder decoder)
272279 * @param chunks the byte arrays to wrap
273280 * @return a new {@code MultiBuffer} backed by the arrays
274281 */
275- public static MultiBuffer wrap (List < ByteBuffer > chunks ) {
276- for (int i = 0 ; i < chunks .size () ; i ++) {
277- ByteBuffer chunk = chunks . get ( i ) ;
282+ public static MultiBuffer wrap (ByteBuffer [] chunks ) {
283+ for (int i = 0 ; i < chunks .length ; i ++) {
284+ ByteBuffer chunk = chunks [ i ] ;
278285 if (chunk .capacity () == CHUNK_SIZE ) {
279286 continue ;
280287 }
281- if (i == chunks .size () - 1 ) {
288+ if (i == chunks .length - 1 ) {
282289 // The last chunk can have a different size
283290 continue ;
284291 }
@@ -306,15 +313,15 @@ public static MultiBuffer mapFromChannel(FileChannel channel) throws IOException
306313 MultiBuffer buf = new MultiBuffer (size );
307314 long remaining = size ;
308315
309- for (int i = 0 ; i < buf .buffers .size () ; i ++) {
316+ for (int i = 0 ; i < buf .buffers .length ; i ++) {
310317 long chunkPos = (long ) i * CHUNK_SIZE ;
311318 long chunkSize = Math .min (CHUNK_SIZE , remaining );
312319 ByteBuffer mapped = channel .map (
313320 FileChannel .MapMode .READ_ONLY ,
314321 chunkPos ,
315322 chunkSize
316323 );
317- buf .buffers . set ( i , mapped ) ;
324+ buf .buffers [ i ] = mapped ;
318325 remaining -= chunkSize ;
319326 }
320327 return buf ;
0 commit comments