0

I need to create data structure, lets call it ByteCache, which containes some amount of bytes and it should support such methods:

1) ByteCache.length() - returns amount of bytes stored in it 2) ByteCache.add(Byte[] bytes) - adds new bytes to the end of presently contained inside 3) ByteCache.get(int offset, int length) - returns byte list from offset to offset+length bytes

It's supposed that there will be one thread writer (which adds bytes to cache) and another thread which reads some amounts of written bytes if there already present.

So what is the best way to do such things in java? May be there is such data structure, or some library ready to use, which I don't know, though I've read about some but didn't get a clue. I'm absolutely new to java, so please be patient.

user3357257
  • 348
  • 1
  • 2
  • 9
  • I'd store the bytes in a fixed-length array, keeping an index pointing to the "last" element. Then grow the array when it fills up. – ajwood Feb 16 '15 at 14:02
  • Take a look at http://docs.oracle.com/javase/7/docs/api/java/nio/ByteBuffer.html - although I am not sure if this "grows" when more space is needed... – BretC Feb 16 '15 at 14:08
  • ajwood, thank you! It looks like good way to solve it.. – user3357257 Feb 16 '15 at 14:13
  • possible duplicate of http://stackoverflow.com/questions/1427200/most-memory-efficient-way-to-grow-an-array-in-java ? – Richard Feb 16 '15 at 14:18
  • Bret, thanks, I've already looked that link and I am not sure about ByteBuffer, so I deсided to ask about "the best way", to get advice from more experienced in java people. – user3357257 Feb 16 '15 at 14:19
  • See the duplicate link. There seems to be two schools of thought. Use ArrayList or create a class that manages an array of arrays byte[][]. When you grow the array of arrays, it should be faster than growing a simple byte[] array. Always use System.arrayCopy when growing. – Richard Feb 16 '15 at 14:21
  • Richard, very helpful link, thanks! And especially for clear summary of that thread. – user3357257 Feb 16 '15 at 14:28

1 Answers1

1

You can implement this with an ArrayList under the hood. ArrayList is an array that expands when more data is added than capacity permits.

Your ByteCache might look like

public class ByteCache {

    ArrayList<Byte> backing = new ArrayList<Byte>();

    public ByteCache(){
    }

    public ByteCache(Byte[] bytes){
        add(bytes);
    }

    public void add(Byte[] bytes){
        for(Byte b : bytes){
            backing.add(b);
        }
    }

    public int length(){
        return backing.size();
    }

    public Byte[] get(int offset, int length){
        if(offset < 0 || length < 1){
            return null;
        }

        Byte[] toRet = new Byte[length];

        for(int i = offset; i < offset + length; i++){
            if(i == backing.size()){
                break;
            }
            toRet[i - offset] = backing.get(i);
        }
        return toRet;
    }
}

You would need to implement your own get() and add() methods, but for length() a call to ArrayList's correct method should be enough.

P.S. ArrayList doesn't exactly expand - a new array is created that is double the size and all items are copied over.

Michael Tontchev
  • 909
  • 8
  • 23
  • 1
    Thank you for your great answer, Michael! Though I now speculating using simple Byte[] array as I was advised by ajwood and Arrays.copyOfRange function for both expanding byte array when needed and for slicing it. There will be quite big amount of bytes in cache, so it seems that copyOfRange is based on System.arraycopy function which is optimized for such operations. – user3357257 Feb 16 '15 at 16:18