1

I am reading the Oracle documentation about creating custom implementations of the Collections interface. The example they give (copied below) instantiates a custom implementation of an ArrayList by passing an Array into the constructor. My understanding is that an ArrayList starts empty and can then expand to arbitrary size by adding elements. By contrast, my recollection is that the size of an Array must be specified at the time the Array is instantiated and that the size of the Array cannot change afterwards.

So why does the example from Oracle below pass an Array into the custom ArrayList implementation? How would you modify the below to be able to accommodate arbitrary expansion and contraction in size after a new MyArrayList has been instantiated?

public static <T> List<T> asList(T[] a) {
    return new MyArrayList<T>(a);
}

private static class MyArrayList<T> extends AbstractList<T> {

    private final T[] a;

    MyArrayList(T[] array) {
        a = array;
    }

    public T get(int index) {
        return a[index];
    }

    public T set(int index, T element) {
        T oldValue = a[index];
        a[index] = element;
        return oldValue;
    }

    public int size() {
        return a.length;
    }
}  
CodeMed
  • 9,527
  • 70
  • 212
  • 364
  • 1
    You cannot, the `a` is final... – Willem Van Onsem Nov 20 '15 at 01:34
  • @CommuSoft Thus, the code above would need to be altered in order to become a true implementation of what we call an ArrayList. So how would it need to be altered? – CodeMed Nov 20 '15 at 01:36
  • @CodeMen: the idea is that you use an array internally, furthermore an additional integer keeps track of the number of items in the list. When you add an item and the internal array is exhausted. You create a new array (for instance with double size), copy the data from the original array and then this becomes the new *active* array. – Willem Van Onsem Nov 20 '15 at 01:37
  • Building custom array lists reduces to resizing arrays. You can view Java's implementation, [here](http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/ArrayList.java#ArrayList.iterator%28%29). – Sotirios Delimanolis Nov 20 '15 at 01:40
  • This question should not have been closed. The answer is that this list cannot be resized -- It inherits the default implementations of add() and remove(), which will throw UnsupportedOperationException. However, this class *is* useful, which is why Oracle provides it as an example. If you want to call a method that takes a list and does not modify it, and what you have is an array, then wrapping your array in a list like this lets you pass it in without having to allocate a whole new array like ArrayList would. – Matt Timmermans Nov 20 '15 at 01:42
  • 1
    @MattTimmermans The question is asking about modifying it to get a fully operational array list. That boils down to being able to resize the backing array. – Sotirios Delimanolis Nov 20 '15 at 01:44
  • `Arrays.asList` does exactly that. http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Arrays.java#3361 The hidden second `ArrayList` in java – zapl Nov 20 '15 at 01:44
  • Yes, it does. As I said, it's useful. @SotiriosDelimanolis, how to resize is the second half of the question. The appropriate answer for *that* is that you would not generally do that for a list that maintains the original backing array, because to resize it will have to allocate a new array, and now the caller doesn't know whether the original array is maintained or not, and that would give the class a strange interface. – Matt Timmermans Nov 20 '15 at 01:48
  • 1
    @matt If you think a (broad) discussion about interface design warrants another question about implementing array lists, vote to reopen. I believe there's enough information in the linked post. – Sotirios Delimanolis Nov 20 '15 at 01:51

0 Answers0