Why does using different ArrayList constructors cause a different growth rate of the internal array?

前端 未结 6 1246
半阙折子戏
半阙折子戏 2021-02-05 15:31

I seem to stumble across something interesting in ArrayList implementation that I can\'t wrap my head around. Here is some code that shows what I mean:



        
6条回答
  •  失恋的感觉
    2021-02-05 15:58

    The short answer to your question is what is in the Java doc: We have two constants because we now need to be able to distinguish the two different initializations later, see below.

    Instead of two constants they could of course have introduced e.g. a boolean field in ArrayList, private boolean initializedWithDefaultCapacity; but that would require additional memory per instance, which seems to be against the goal to save a few bytes of memory.

    Why do we need to distinguish those two?

    Looking at ensureCapacity() we see what happens with DEFAULTCAPACITY_EMPTY_ELEMENTDATA:

    public void ensureCapacity(int minCapacity) {
        int minExpand = (elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
            // any size if not default element table
            ? 0
            // larger than default for default empty table. It's already
            // supposed to be at default size.
            : DEFAULT_CAPACITY;
    
        if (minCapacity > minExpand) {
            ensureExplicitCapacity(minCapacity);
        }
    }
    

    It seems that it is done this way to be somewhat 'compatible' to the behavior of the old implementation:

    If you did initialize the list with the default capacity, it will actually be initialized with an empty array now, but, as soon as the first element is inserted, it will basically revert to the same behavior as the old implementation, i.e. after the first element is added, the backing array has the DEFAULT_CAPACITY and from then on, the list behaves the same as previously.

    If, on the other hand, you explicitly specifiy an inital capacity, the array does not 'jump' to DEFAULT_CAPACITY but grows relatively from your specified initial capacity.

    I figure the reason for this 'optimization' may be for cases where you know you will be only storing one or two (i.e. less than DEFAULT_CAPACITY) elements in the list and you specify the initial capacity accordingly; in these cases, for example for a single-element list, you only get a single-element array, instead of a DEFAULT_CAPACITY-sized.

    Don't ask me what the practical benefit is of saving nine array elements of a reference type. Might be up to about 9*64 bit = 72 bytes of RAM per list. Yeay. ;-)

提交回复
热议问题