2015-04-10

Java ArrayList resize

Once I had an array:

    static final Apple[] apples = new Apple[4];

Then circumstances changed so, Apple became generic, so my code changed to

    static final Apple<T>[] apples = new Apple<T>[4];

which produced compile errors as Cannot create a generic array of Apple<T>, so I was forced to switch to ArrayList like:

    static final ArrayList<Apple<T>> apples = new ArrayList<>(4);
    // 4 means capacity here not size.

I have some code in a static initializer block that fills apples using calculated indexes, so it is not a sequence of add(e) calls and it is not desirable for me to rearrange it that way.

I would like to resize the array to have 4 elements, all of them null. A manual way to achieve it is this:

    static {
      for(int i=0; i<4; ++i)
        apples.add(null);
      // ORIGINAL index-magic based code here.
    }

Which is super effective but not so elegant.

Unfortunately all my search efforts on the Internet were derailed because of posts that suggest ensuring capacity and then adding elements with add(e). None of them addressed the original question of resizing an ArrayList using a filler element. The OPs of those questions were satisfied with those answers, but I really would like to have the answer to the original question.

Until then this will go:

  /**
   * Resizes and returns an {@code ArrayList}.
   * Capacity is not freed upon shrinking. At most one allocation happens.
   * 
   * @param list
   *          Input to be altered, return value.
   * @param size
   *          Desired size
   * @param filler
   *          Additional elements - if any - will be set to this.
   * @return Altered list.
   */
  public static <T> ArrayList<T> resize( ArrayList<T> list, int size, T filler ) {
    for( int i = list.size(); i > size; --i )
      list.remove( i - 1 );
    list.ensureCapacity( size );
    for( int i = list.size(); i < size; ++i )
      list.add( filler );
    return list;
  }

  /**
   * Resizes and returns an {@code ArrayList}.
   * Capacity is not freed upon shrinking. At most one allocation happens.
   * Additional elements - if any - will be set to null.
   * 
   * @param list
   *          Input to be altered, return value.
   * @param size
   *          Desired size
   * @return Altered list.
   */
  public static <T> ArrayList<T> resize( ArrayList<T> list, int size ) {
    return resize( list, size, null );
  }

It is slower than the original for based ad-hoc solution, but it is quicker to read at the place of usage, and resizing of arrays do not (should not) happen that often, as I would seriously doubt the general quality of a code where an array resizing takes place at a hot-spot.

No comments:

Post a Comment