Tutorial :When to Be Specific About the Type of List You Want


Let's say I have a class which, internally, stores a List of data:

import java.util.List;    public class Wrapper  {      private List<Integer> list;        public Wrapper(List<Integer> list)      {          this.list = list;      }        public Integer get(int index) { return list.get(index); }  }  

For the sake of this example, pretend it's a useful and necessary abstraction. Now, here's my concern: As a programmer who knows the underlying implementation of this class, should I be specific about which type of List I ask for in the constructor? To demonstrate, I've made this test:

import java.util.List;  import java.util.ArrayList;  import java.util.LinkedList;    public class Main  {      public static void main(String[] args)      {          long start;          List<Integer> list1 = new ArrayList<Integer>();          List<Integer> list2 = new LinkedList<Integer>();          Wrapper wrapper1, wrapper2;            for(int i = 0; i < 1000000; i++)          {              list1.add(i);              list2.add(i);          }            wrapper1 = new Wrapper(list1);          wrapper2 = new Wrapper(list2);            start = System.currentTimeMillis();            wrapper1.get(500000);            System.out.println(System.currentTimeMillis() - start);            start = System.currentTimeMillis();            wrapper2.get(500000);            System.out.println(System.currentTimeMillis() - start);      }  }  

As you most likely know, randomly accessing an element takes a bit more time with a linked list as opposed to an array. So, going back to the Wrapper constructor, should I be general and allow for any type of List, or should I specify that the user pass an ArrayList to ensure the best possible performance? While in this example, it may be easy for the user to guess as to what the underlying implementation of the method get is, you could imagine that this was something more complex. Thanks in advance!


The whole point of interfaces is to allow for agnosticism about the underlying implementation. The very use of the List type as opposed to LinkedList or ArrayList is to allow general operations without having to worry about this kind of problem. As long as your code can be written without having to rely upon methods not exposed by List you don't need to worry.

It is likely a user of this class is writing code that has other requirements on the type of list they use, they might be appending lots into the middle of the list for instance where a LinkedList excels. As such you should accept the most generic type possible and assume the user has a good reason for using that type.

This isn't however to stop you perhaps including a javadoc comment that the use of an ArrayList might be better if there is no difference in any other use of the application.


So, going back to the Wrapper constructor, should I be general and allow for any type of List?

Is the intention of the wrapper to support any type of list? or only ArrayList?

...or should I specify that the user pass an ArrayList to ensure the best possible performance?

If you leave the general List it will be just fine. You let the "client" of that class to decide whether or not he may use ArrayList. Is up to the client.

You may also use the RandomAccess interface to reflect your intention, but since it is only a marker interface probably it wont make much sense.

So again, leaving it as general List will be enough.


Go with ArrayList if you are going to be randomly accessing from this list or you think you will be adding to this list a lot.

Go with LinkedList if you are going to accessing the elements in series most of the time.


This probably is something one can argue about.

My arguments for requiring a specific type are:

  • The wrapping class really knows which type would be best-suited in all the situations the wrapping class is used in. Random access is a good example for this -- it's unlikely that there is a better list implementation for this scenario than a list backed by an array.
  • The wrapping class actually makes assumption about the implementation. If such assumptions are made, make sure they are fulfilled by requiring the appropriate type.

The argument against requiring a specific type is:

  • The wrapping class is used in different scenarios and there are different implementations of List that are more or less suited for a specific scenario. I.e., it should be up to the caller to find the implementation that suits the scenario best. There also may be cases in which the best (TM) implementation of the List had not been invented yet by the time the wrapper class was written.


I think it depends on what you're trying to achieve with the Wrapper class and/or what you expect clients of Wrapper to use it for.

If your intent is to just provide a wrapper for a List, where clients shouldn't expect a certain level of performance from get() (or whatever the method's name is), then your class looks fine to me as-is, except for the fact that it's just a reference to the constructor's listparameter that's getting copied, rather than the contents of the list itself (more on this in the 3rd point below).

If, however, you tell your clients to expect get() to be very responsive, some alternatives come to mind (there might be more):

  1. Write a set of constructors that accept only those implementations of a List that you know have high performance for whatever operation(s) get() will execute on it. For example:

} // if I knew how to avoid this brace I would...

 public Wrapper {       Wrapper(ArrayList<Integer> list) { ... }       Wrapper(KnownListImplementationThatWillMakeMyGetMethodFast<Integer> list) { ... }         //...   }   

One drawback of doing this is that if another efficient List implementation comes along, you'll have to add another constructor for it.

  1. Leave your Wrapper class untouched, but inform your clients (via some form of documentation, say, class comments, a README file, etc.) that certain operations on whatever List implementation they pass in are expected to have a certain performance (e.g. "get() must return in constant time"). If they then "misuse" your wrapper by passing in a LinkedList, it's their fault.

  2. If you want to guarantee that your get() implementation is quick, it's worth copying the list you receive in the constructor into a member data structure that meets your performance constraints. This can be an ArrayList, some other List implementation you know of, or a container that doesn't implement the List interface altogether (e.g. something special-purpose you've written). With regard to what I said earlier about copying the List's contents vs. copying a reference to it, any "write" operations you perform on the reference you have will not flow through to your client's copy of the List if you copy its contents. This is usually a good way to avoid the client wondering why their copy of the list gets touched when invoking operations on your Wrapper, unless you explicitly tell them to expect this behavior.

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Next Post »