Menu

#87 Ctor TxxxArrayList(xxx[]) has capacity that is too big

Research
closed
Performance (6)
3
2012-09-24
2009-03-15
Idan Avisar
No

Often, when a collection is instantiated with an array, no further additions are made to the collection.
The fact that the TxxxArrayList(xxx[]) Ctor creates a capacity that is the greater of the length of the array and DEFAULT_CAPACITY may result in waste of memory.

JCF Collections do not do this.

If a client wants to generate a TxxxArrayList "wrapper" of an existing array, he must write this cumbersome code to avoid wasting memory:

xxx[] array;

TxxxArrayList tList = new TxxxArrayList(array.length);
tList.add(array);

rather than

TxxxArrayList tList = new TxxxArrayList(array);

Discussion

  • Rob Eden

    Rob Eden - 2009-03-16

    I guess I don't agree that this is a problem, unless you're seeing different behavior than I am. The minimum size is 10, which is certainly not a large value. The argument for not going too small is that the backing array grows by doubling the size. For "traditional" usage where an empty list is created and then added to, there would be a significant performance hit if we dropped the minimum size (say, to 1) and then added entities to it because it would have to grow the backing array many more times.

    Please provide more data about what size arrays you're looking at, how many extra entities exist and whether or not you agree with my analysis. Thanks!

    Dropping priority until impact is known...

     
  • Rob Eden

    Rob Eden - 2009-03-16

    Whoops... really dropping priority this time.

     
  • Idan Avisar

    Idan Avisar - 2009-03-17

    I don't think that you should reduce the default capacity for a newly created empty list.

    Only the Ctor that accepts an array should not grow to a larger capacity than the given array. I believe that most cases that init an array with another array will not have further additions...

    This conforms to the standards of java.util.ArrayList. The default Ctor init's the capacity to 10.
    The Ctor that accepts an int init's the capacity to the size given by the user.
    The Ctor that accepts a Collection init's the capacity to exactly the size of the given Collection.

    In my case, I have a slew of objects (on the order of 10000) holding small arrays. If each array had a capacity of 10 rather than the average of 5, it would double the memory usage...
    I use the TxxxArrayList rather than the original primitive array because I want the arrays hashCode to reflect their contents (primitive array hashCode is unique for each instance).

     
  • Rob Eden

    Rob Eden - 2009-03-17

    The other option is that you could do:

    TxxxArrayList tList = new TxxxArrayList(array);
    tList.trimToSize();

    Is that any more appealing?

     
  • Idan Avisar

    Idan Avisar - 2009-03-18

    I considered that - it seems to me a waste allocating and then trimming down...
    Currently, in my code I use the Ctor that accepts an int and then call add(long[]).

    I must reiterate that I believe that when you can do things one way or another, Trove should conform to the JCF standard...
    In java.util.ArrayList, the Ctor that accepts a Collection, allocates an array of that size; w/o doing max with the its DEFAULT_CAPACITY.

    I don't see why Trove lists should behave differently...

     
  • Rob Eden

    Rob Eden - 2009-03-18

    The size of the internal array created by the constructor is as much an implementation detail as anything I've ever heard of. :-)

    The rule will always be: if you want to be sure you're using the minimum memory possible, use trimToSize().

    That being said, I'll see what I can do...

     
  • Jeff Randall

    Jeff Randall - 2009-09-15

    Behavior changed for Trove 3.