Java - ByteBuffer or ArrayList <Byte>?

I recently created a wrapper to read and write data to an array byte

. I used to do this ArrayList<Byte>

, but I was wondering if this is the most efficient way to do it, because:

  • addAll()

    doesn't work with arrays byte

    (even using Arrays.asList()

    that returns me List<Byte[]>

    ). To fix this, I just loop and add byte

    in each loop, but I suppose this involves a lot of function calls and therefore has performance.
  • The same happens when receiving byte[]

    from ArrayList

    . I cannot cast from byte[]

    to byte[]

    , so I have to use a loop for that.
  • I suppose storing a byte instead of a byte uses more memory.

I know that ByteArrayInputStream

u ByteArrayOutputStream

can be used for this, but it has some disadvantages:

  • I wanted to implement methods to read various types of data in different byte orders (eg readInt

    , readLEInt

    , readUInt

    etc.), while these classes can read or write a byte or array of bytes is not a problem, because I can fix it in the wrapper ... But here comes the second problem.
  • I wanted to be able to write and read at the same time because I am using this to unzip some files. And so to create a wrapper for this, I would need to include both ByteArrayInputStream

    and ByteArrayOutputStream

    . I don't know if they can be synchronized in any way or if I have to write all the data of one to the other every time I write to the wrapper.

So here's my question: would the use be ByteBuffer

more efficient? I know what you can take integers

, floats

etc. From there, even having the ability to change the byte order. I was wondering if there is a real performance change between using ByteBuffer

and ArrayList<Byte>

.

+3


source to share


3 answers


Definitely ByteBuffer or ByteArrayOutputStream . In your case, ByteBuffer seems fine. Check out the Javadoc as it has good techniques. For putInt / getInt etc. You can set the order (from those 4 bytes)

byteBuffer.order(ByteBuffer.LITTLE_ENDIAN);

      



With files, you can use getChannel()

or variations and then use MappedByteBuffer

.

ByteBuffer can wrap a byte array or allocate.

+3


source


Keep in mind that every object has overhead associated with it, including a bit of memory for each object and garbage collection when it goes out of scope.



Using List<Byte>

would mean creating / garbage collecting the object per byte, which is very wasteful.

+1


source


ByteBuffer is a wrapper class around a byte array, it doesn't have a dynamic size like ArrayList, but it consumes less memory per byte and is faster. If you know the size you want then use a ByteBuffer, if you don't, then you can use a ByteArrayOutputStream (and possibly wrapped ObjectOutputStream, it has some methods for writing different kinds of data). To read the data that you wrote in ByteArrayOutputStream you can extend ByteArrayOutputStream and then you can access buf [] and count fields, these fields are protected so you can access them from extension class, it looks like this:

public class ByteArrayOutputStream extends OutputStream {

    /**
     * The buffer where data is stored.
     */
    protected byte buf[];
    /**
     * The number of valid bytes in the buffer.
     */
    protected int count;
...
}


public class ReadableBAOS extends ByteArrayOutputStream{
    public byte readByte(int index) {
        if (count>index) {
            throw new IndexOutOfBoundsException();
        }
        return buf[index];
    }
}

      

so that you can use some of the methods in the extending class to read multiple bytes from the underlying buffer without having to make a copy of your content every time as the byByteArray () method does.

0


source







All Articles