10 Replies - 9330 Views - Last Post: 22 February 2013 - 03:13 PM

#1 darek9576  Icon User is online

  • D.I.C Lover

Reputation: 198
  • View blog
  • Posts: 1,689
  • Joined: 13-March 10

Interfaces and Collections

Posted 22 February 2013 - 07:18 AM

I have been asking myself this question for a looong time and could never come up with an answer so here it goes:

Let's say we have a class Teacher that contains a List<Student>:
class Teacher
{
      private List<Student> list;
      public Teacher(){ list = new LinkedList<>(); }
}


Because we have declared the list to be referenced by List<> then we can only use methods that can be found in the List interface. My question is: what is the point and why bother? What is the point of making it a List<> since i will not be able to use all the goodies that come from LinkedList as addFirst() addLast() etc.

One obvious advantage is when we have:
public void print(List<Student> list){}


Yes, in this case, if we pass in ArrayList or LinkedList or something else,it will work. Thats great. But what is the point of underlying data structure if we can only manipulate it via List interface.

Hope i made my question clear. Hard to put the idea across. Thanks.

Is This A Good Question/Topic? 1
  • +

Replies To: Interfaces and Collections

#2 Ryano121  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1362
  • View blog
  • Posts: 3,002
  • Joined: 30-January 11

Re: Interfaces and Collections

Posted 22 February 2013 - 07:40 AM

*
POPULAR

The main point is to decouple your code from one kind if implementation of the interface you're using. If you declare the variable type as a LinkedList straight off the bat, you tie yourself into a load of dependencies if you go about using all the implementation specific methods. On the other hand if you declare it as a List, it can be any kind of list. The point is it won't matter - it will work in any case.

In your example using a List is preferable over LinkedList as you don't need any of the behaviour of a LinkedList in this case. Therefore this allows you to decouple your code as much as possible away from a specific kind of list which is a good thing. If you wrote it as an ArrayList and then decided you really needed a LinkedList for performance reasons when deleting elements in the middle, you would need to go through and modify each and every declaration. Something that is a real pain in a large library.

I know where you are coming from and I wondered the same thing for a while. If I declare it as an interface then I lose all the nice methods of the implementations. The thing is a lot of the time (including your example) you don't really need those nice methods. You just need an interface that exposes common members to add ,remove etc. You don't want to worry about implementation. You can abstract that away which is a good thing.

Programming to an interface makes your code a lot more flexible and more resilient when the day comes when you need to make changes to implementation. Hope that makes sense.
Was This Post Helpful? 7
  • +
  • -

#3 jon.kiparsky  Icon User is online

  • Pancakes!
  • member icon


Reputation: 7737
  • View blog
  • Posts: 13,072
  • Joined: 19-March 11

Re: Interfaces and Collections

Posted 22 February 2013 - 08:57 AM

Yeah, pretty much nailed it.

Best practice is to use the most flexible form that suits your needs, and to program to make your requirements as flexible as possible.
Here's another use case to consider:
Suppose as part of a project you write an object that consumes an ArrayList and spits out some result. All goes well, the object does its job, and you're as contented as a clam. You write a bunch of client objects which happily produce ArrayLists and get back results, and we're all good.
So now you have a lot of investment in ArrayList.
What happens if you provide this object to someone and they have a similar investment in objects that produce LinkedLists?

Don't get the wrong message from this: there are very good reasons to use particular collections instead of abstract ones, and if those reasons apply, you should use them. For example if you want a set and you would like to be able to access the members of the set in sorted order, a TreeSet is the right thing to use. However, if you simply want Set behavior (a collection which contains at most one of any object) and you don't care about the order of access, then Set will be less limiting.

It's also good practice to know what implementations a client might end up using, and provide some indication of what operations you perform. A client would really like to know, for example, if you're doing this:
public boolean foo (List <Bar> l){
  for (int i = 0; i < l.length(); i++)
    if (l.get(i).isConfundible() return true;
  return false;
}


Because this will have very different performance characteristics depending on whether l is an ArrayList or a LinkedList
Was This Post Helpful? 3
  • +
  • -

#4 farrell2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 838
  • View blog
  • Posts: 2,575
  • Joined: 29-July 11

Re: Interfaces and Collections

Posted 22 February 2013 - 09:41 AM

Great explanation, Ryano! I'd like to also mention that if you need a method from a more specific list, you can cast. Like if you needed trimToSize() in ArrayList;

((ArrayList<Student>)list).trimToSize()


Was This Post Helpful? 2
  • +
  • -

#5 darek9576  Icon User is online

  • D.I.C Lover

Reputation: 198
  • View blog
  • Posts: 1,689
  • Joined: 13-March 10

Re: Interfaces and Collections

Posted 22 February 2013 - 09:50 AM

Good explanations guys. One follow up question.

Let's say i have a
List<T> list = new ArrayList<>();


Then, i have the method that adds to index 0, like this:
publi void addAtTheBeginning(T value){
    list.add(0, value);
}

So the performance of 
the method would be much better if it was a LinkedList. Let's say i change it without touching the method:
List<T> list = new LinkedList<>();


will i get the performance boost?
Was This Post Helpful? 0
  • +
  • -

#6 jon.kiparsky  Icon User is online

  • Pancakes!
  • member icon


Reputation: 7737
  • View blog
  • Posts: 13,072
  • Joined: 19-March 11

Re: Interfaces and Collections

Posted 22 February 2013 - 09:53 AM

View Postfarrell2k, on 22 February 2013 - 11:41 AM, said:

I'd like to also mention that if you need a method from a more specific list, you can cast. Like if you needed trimToSize() in ArrayList;

((ArrayList<Student>)list).trimToSize()




This only works if the List was originally an ArrayList, though. Don't try this if you're accepting some List l as an argument, or you'll get a runtime exception any time someone calls this with a LinkedList (or a MyList or a CheckOutMyCoolImplementationOfArrayList)
Was This Post Helpful? 0
  • +
  • -

#7 farrell2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 838
  • View blog
  • Posts: 2,575
  • Joined: 29-July 11

Re: Interfaces and Collections

Posted 22 February 2013 - 09:55 AM

I'd be surprised to discover that the performance is not the same in that situation, adding to the very beginning of a list. It might be. I doubt you'd even have to worry about it, however, unless you're running something that does thousands of those transaction a second. :)

I think the original question was really good.

This post has been edited by farrell2k: 22 February 2013 - 09:55 AM

Was This Post Helpful? 0
  • +
  • -

#8 Ryano121  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1362
  • View blog
  • Posts: 3,002
  • Joined: 30-January 11

Re: Interfaces and Collections

Posted 22 February 2013 - 09:55 AM

Quote

will i get the performance boost?


That's the beauty of polymorphism :)

This post has been edited by Ryano121: 22 February 2013 - 09:56 AM

Was This Post Helpful? 1
  • +
  • -

#9 jon.kiparsky  Icon User is online

  • Pancakes!
  • member icon


Reputation: 7737
  • View blog
  • Posts: 13,072
  • Joined: 19-March 11

Re: Interfaces and Collections

Posted 22 February 2013 - 10:04 AM

View Postdarek9576, on 22 February 2013 - 11:50 AM, said:

Good explanations guys. One follow up question.

Let's say i have a
List<T> list = new ArrayList<>();


Then, i have the method that adds to index 0, like this:
publi void addAtTheBeginning(T value){
    list.add(0, value);
}

So the performance of 
the method would be much better if it was a LinkedList. Let's say i change it without touching the method:
List<T> list = new LinkedList<>();


will i get the performance boost?



Yes. The available functionality is determined by the interface, but the actual implementation is all in the actual object.

So the compiler sees that this is a List, and knows that it can add, remove, get, and so forth, but when it calls those methods it calls the methods on the List it's given. So you could implement a JokeList which would toss a coin and only add() or remove() or whatever on heads (and returned a random boolean or a null or something on tails). Anyone using thing would get completely nonlinear results, but it would be a perfectly good List from the compiler's point of view.
Was This Post Helpful? 1
  • +
  • -

#10 darek9576  Icon User is online

  • D.I.C Lover

Reputation: 198
  • View blog
  • Posts: 1,689
  • Joined: 13-March 10

Re: Interfaces and Collections

Posted 22 February 2013 - 10:07 AM

Great. I think i finally get it. I was always aware of the "write to interface stuff" but i needed to make sure i get it. Thank you.
Was This Post Helpful? 0
  • +
  • -

#11 blackcompe  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1155
  • View blog
  • Posts: 2,533
  • Joined: 05-May 05

Re: Interfaces and Collections

Posted 22 February 2013 - 03:13 PM

Good answer Ryano. Beside the power that polymorphism brings and leveraging code re-use, decoupling your code is of the utmost importance when talking about good design. Coding to interfaces leaves your code flexible for future changes.

Quote

I'd be surprised to discover that the performance is not the same in that situation, adding to the very beginning of a list. It might be. I doubt you'd even have to worry about it, however, unless you're running something that does thousands of those transaction a second.


Your right in that there's no practical difference when the lists are small or there aren't a lot of prepend operations, but in theory there's a difference. There are trade-offs between all the data structures. Prepending to a linked list is a constant time operation, whereas prepending to an arraylist is linear in the size of the list. The array elements must shifted. That's an obvious disadvantage, but arraylists have constant time access, whereas linked lists don't for inner elements. Linked lists also can't take advantage of cache locality. It's common to see node memory allocated all over the place (which results in more cache misses and having to access the slower main memory), whereas array memory is allocated in one fell swoop.

This post has been edited by blackcompe: 22 February 2013 - 03:17 PM

Was This Post Helpful? 1
  • +
  • -

Page 1 of 1