Java polymorphism (ArrayList and List) - java

I was looking at this old question and its chosen answer.
The chosen answer was originally,
ArrayList<ArrayList<Individual>> group = new ArrayList<ArrayList<Individual>>(4);
But was later modified to recommend this instead
List<List<Individual>> group = new ArrayList<List<Individual>>(4);
I didn't see an explanation for this on the page, can someone please explain why the second one is recommended over the first one? (I'm assuming it has to do with polymorphism)

This is code to interface. Here you can see the assignment is done to a List interface not the ArrayList class which is implementing the List. ArrayList, LinkedList implements List interface, the same way, you can have your own List implementing Class as well. So, in future if you want to change the implementation in such a way that instead of ArrayList object you want some other List implementation like LinkedList then you can easily modify the code like this -
List<List<Individual>> group = new ArrayList<List<Individual>>(4);
to
List<List<Individual>> group = new LinkedList<List<Individual>>(4)
This change will have no impact on the other part of your code which uses group variable as for other this is a List object not an Arraylist or LinkedList object. It is not going to break your code and you don't have to waste your time to modify your code to accomodate this change.

Related

What is the difference in time & space complexity between declaring an ArrayList object and a List object?

I know that an instance of ArrayList can be declared in the two following ways:
ArrayList<String> list = new ArrayList<String>();
and
List<String> list = new ArrayList<String();
I know that using the latter declaration provides the flexibility of changing the implementation from one List subclass to another (eg, from ArrayList to LinkedList).
But, what is the difference in the time and space complexity in the two? Someone told me the former declaration will ultimately make the heap memory run out. Why does this happen?
Edit: While performing basic operations like add, remove and contains does the performance differ in the two implementations?
The space complexity of your data structure and the time complexity of different operations on it are all implementation specific. For both of the options you listed above, you're using the same data structure implementation i.e. ArrayList<String>. What type you declare them as on the left side of the equal sign doesn't affect complexity. As you said, being more general with type on the left of the equal sign just allows for swapping out of implementations.
What determines the behaviour of an object is its actual class/implementation. In your example, the list is still an ArrayList, so the behaviour won't change.
Using a List<> declaration instead of an ArrayList<> means that you will only use the methods made visible by the List interface and that if later you need another type of list, it will be easy to change it (you just change the call to new). This is why we often prefer it.
Example: you first use an ArrayList but then find out that you often need to delete elements in the middle of the list. You would thus consider switching to a LinkedList. If you used the List interface everywhere (in getter/setter, etc.), then the only change in your code will be:
List<String> list = new LinkedList<>();
but if you used ArrayList, then you will need to refactor your getter/setter signatures, the potential public methods, etc.

What kind of List is List<Object> list = Database.getAllData();?

I have the following question:
if I have the following line of code:
List<Position> allPos = posDBM.getAllPos();
Position is an object
posDBM is a SQLite Database Manager class, which manages the SQLite database,
getAllPos() returns all database data.
The return type of getAllPos() is List<Position>.
If I want to initialize a List<> like this List<Position> pos = new, I have to specify the type of the List (ArrayList, LinkedList, etc.) .
So back to my question, what kind of List do I have, after I filled the list from the database?
I would guess it's an ArrayList , but I can't find any source to back this up. It's just a matter of interest...
You don't have to know; that's the point. The interface is what matters to you, not the implementation.
You can't know without looking at the source of that method. But even if you do, it's immaterial to your client. All you call are List methods.
That you will find in getAllPos() source code. List<Position> due to Polymorphism will accept all classes implementing List interface.
It you are just curious, then one way to find out is to do something like this:
List<Position> allPos = posDBM.getAllPos();
System.out.println("The class is " + allPos.getClass().getName());
Of course, you don't need to know ... because you don't need to instantiate the list implementation class yourself. The database management code deals with that.
The returned List<Position> is a generic or a Strongly Typed list. The option that you were asking is about ArrayList which specifies a list that can take up any object. This will require an overhead of Boxing and Unboxing when writing / reading using the ArrayList.
Ideally you should not worried about the actual implementation , once you have List returned from the method call , you can just iterate over it like this .
List<Position> allPos = posDBM.getAllPos();
for(Position position : allPos){
//Your code goes here
}
And if you want to initialize a new list you can do it in many ways by using different implementations of List interface , now which implementation you want to choose very much depends on your requirement.
I would suggest you to add a breakpoint and see allPos variable after posDBM.getAllPos(), the debugger should tell you the Type.

Should I use ArrayList<?> or List<?>

I'm developing for Android and wondered, what are the main differences between an ArrayList and a List?
For the handling of objects collection in Java, Collection interface have been provided. This is available in java.util package.
"List" is an interface, which extends collection interface, provides some sort of extra methods than collection interface to work with collections. Where as "ArrayList" is the actual implementation of "List" interface.
The ArrayList class has only a few methods in addition to the methods available in the List interface. There is not much difference in this. The only difference is, you are creating a reference of the parent interface in the first one and a reference of the class which implements the List (i.e) the ArrayList class in the second. If u use the first, you will be able to call the methods available in the List interface and you cannot make calls to the new methods available in the ArrayList class.Where as, if you use the second one, you are free to use all the methods available in the ArrayList.
EDIT:
In Java Applications development, when you are supposed to pass the collection framework objects as arguments to the methods, then it is better to go with
List tempList = new ArrayList();
somemethodcall(tempList);
because, in future due to performance constraints, if you are changing the implementation to use linkedlist or some other classes which implements List interface, instead of ArrayList, you can change at only one point (i.e) only the instantiation part. Else you will be supposed to change at all the areas, where ever, you have used the specific class implementation as method arguments.
user370305 gives an exact explanation. This may also help you understand the collections hierarchy in Java.
List is interface which ArrayList implements. If you are trying to create a method which needs a List of some kind but you are not bothered what implemntation is actually used then use List.
If you are actually instantiating a class then you have to pick some implementation of List one of which is ArrayList
List<String> l1 = new ArrayList<String>();
would be an example.
You can not instantiate an interface and so would get an error if you tried to do the following:
List<String> l2 = new List<String>();
There is a good article on wikipedia about that, where the arraylist is called "dynamic array".
If you are trying to optimize your application you should take a look at the table next to the article.
List is an interface and ArrayList is an implementation of the List interface. The ArrayList class has only a few methods in addition to the methods available in the List interface.
Have a look at the short article on JavaBeat - Difference Between List and ArrayList?

Declaring a LinkedList in Java

I always learn when we declare a collection we should do, Interface ob = new Class(), if i want to use for example a LinkedList i'll do List ob = new LinkedList(), but then i can't have access to all methods from LinkedList.. Isn't LinkedList ob = new LinkedList() 100% correct?
Isn't LinkedList ob = new LinkedList() 100% correct?
Well I'd suggest using the generic form, but sure - if you want to use functionality which is specific to LinkedList, you need to declare the variable accordingly.
You might want to check whether the Deque<E> or Queue<E> interfaces have what you want though. If they do, use those in-keeping with the idea of describing what you need rather than what implementation you'll use.
Yes,
LinkedList<...> items = new LinkedList<...>();
is perfectly correct if you know that items will depend on methods of LinkedList<T> that are not captured in the List<T> interface.
You should always try to keep the declaration at the highest level possible, meaning that you should stop at the highest level that provides all the functionality that you need: if List methods are not enough, you're perfectly fine with your LinkedList declaration.
If you actually have a need to use methods that are not on the List interface, there is certainly nothing wrong with using LinkedList's API. The general rule of programming to the List interface recognizes that 1) it's pretty rare to need those methods, and 2) in most people's experience, it's way more likely that I discover I need to sort the list and/or use a lot of random access, and decide to switch to an ArrayList, than it is I need one of the methods only LinkedList has.
It may be also that you could be programming to the Queue interface, if you find List isn't giving you what you need.
The rule "always code to interfaces" must be taken with some flexibility. What you are suggesting is fine, and as you came to the conclusion, the only option.
As a side note, coding to concrete classes like this is faster is most JVMs. Deciding whether the performance is worth breaking the rule is the hard thing to decide.
LinkedList is a generic. You should be doing:
LinkedList<String> linkedList = new LinkedList<String>();
(or whatever else you need to store in there instead of String)
Not exactly 100% correct.
A preferred way to declare any collection is to include the data type it's holding. So, for your example, it'd be LinkedList<Integer> ob = new LinkedList<Integer>();.
Nope.. This would be wrong, at the later stages if he wants to change his implementation from linked list to any other implementation of list type he will go wrong... So better to use the interface level declaration.
I won't always suggest you to use generics .....
Coz sometimes you may need to wrap different objects as here....
String str="a string";
boolean status=false;
LinkedList ll = new LinkedList();
ll.add(str);
ll.add(status);
In some situations like case of RMI, u can only send serialized data.....and suppose you want to send a class object(which is unserialized).......There you can wrap the members of the class(primitives) in a LinkedList and pass that object as a whole.......not worrying about the huge number of arguments......
Consider for eg:
public Class DataHouse
{
public int a;
public String str;
.
.
.
}
Now Somewhere u need to pass the objects....
You can do the following....
DataHouse dh =new DataHouse();
LinkedList ll = new LinkedList();
ll.add(dh.a);
ll.add(dh.str);
// Now the content is serialized and can pass it as a capsuled data......
you can still have access to LinkedList methods by using List, all you have to do is to type cast
for example
((LinkedList)ob).add()
The point of using generic List and not LinkedList is because in case you simply change the type of lists you are using (let's say double linked list) your program will still work Generics are to simplify your code to be more portable and more "changeable"
Actually it would be better if it would be parametrized as both are raw types.

What is the difference between creating instance by extending superclass and by extending its own class?

For example:
List<String> list = new ArrayList<String>();
vs
ArrayList<String> list = new ArrayList<String>();
What is the exact difference between these two?
When should we use the first one and when should we use the second?
Use the first form whenever possible (I would even say: use Collection if sufficient). This is especially important when accepting input from client code (method arguments). Sometimes, for the convenience of the client code/library user it is better to accept the most generic input you can (like Collection) and deal with it rather than forcing the user to convert arguments all the time (user has LinkedList but the API requires ArrayList - terrible).
Use the second form only when you need to invoke methods on list variable that are defined in ArrayList but not in List (like ArrayList.trimToSize()). Also when returning data to the user consider (but this is not the rule of thumb) returning more specific types. E.g. consider List over Collection so the client code can easier deal with the result. However! Returning too specific types (e.g. ArrayList) will lock your implementation for the future, so try to find a compromise.
This is a general rule - use the most general type you can. Even more general: use common sense.
List is not a superclass, it is an interface.
By using List rather than ArrayList, you make sure that users of your list will only use methods that are defined on List. Meaning that you can change the implementation to (for example) Vector, without breaking the existing code.
So, use the first form.
The first form is the most desirable one because you hide the implementation (ArrayList) from the rest of your code and ensure your code only works with the abstraction (List). The advantage of this is that your code will be more generic and therefore easier to adapt, for example when you change from using an ArrayList to a LinkedList, Vector or own List implementation. It also means local changes are less likely to cause changes in other parts of your code ('ripple-effect'), increasing your code's maintainability.
You need the second form when you want to do things with your variable that are not offered by the List interface, for example ensureCapacity or trimToSize
EDIT: extra explanation of changing the implementation
Here is an example of declaring a variable as a Collection (an even more generic interface in java.util):
public class Example {
private Collection<String> greetings = new ArrayList<String>();
public void addGreeting(String greeting) {
greetings.add(greeting);
}
}
Now suppose you want to change the implementation in order to store unique greetings, and therefore switch from ArrayList to HashSet. Both are implementations of the Collection interface. This would be easy in this case because all the existing code treats the greetings field as a Collection:
public class Example {
private Collection<String> greetings = new HashSet<String>();
public void addGreeting(String greeting) {
greetings.add(greeting);
}
}
There is an exception. If there is code which casts the greetings field back to its implementation, this makes that code 'implementation-aware', violating the information-hiding you tried to achieve, for example:
ArrayList<String> greetingList = (ArrayList<String>) greetings;
greetingList.ensureCapacity(42);
Such code would cause a runtime error 'java.lang.ClassCastException: java.util.HashSet incompatible with java.util.ArrayList' if you change the implementation to HashSet, so this practice should be avoided if possible.
There are some advantages of using interfaces against concrete classes:
You are not stuck to concrete implementation (you can easy change it without modifying code)
Your code is clearer as no methods of concrete class are available
You need concrete implementation only in case if you USE some features of it.
E.g. we have Matrix interface and have two concrete implementations SparseMathix and FullMatrix. If you want to effectively multiply them you CAN use some implementation details of SparseMatrix otherwise performance MAY be too slow.

Categories