1z0-808 Oracle Java SE 8 Programmer – Collections part 1
- Section Overview
We’ve talked about the array and we saw that it’s a great way of creating collections of related objects together. But we saw that there were some limitations as well. So we’re going to look at something that’s a little bit more flexible. It’s called a collection. And so we’ll start right away talking about array lists and so on. Let’s start with lecture number one.
- When Arrays Are Not Enough
When we code, we very frequently have to put together collections of things. We’ve seen that we have an Array, and that’s one way that we can put together a collection. But there is an alternative in Java. The API includes something called the Collection framework. And this is a set of prebuilt data structure components that are part of the Java Util package. Now, arrays and collections have their strengths and weaknesses. Both have their place in Java applications. But it’s a good idea to know what these differences are so you can choose the appropriate data structure. So here’s some high level differences between an Array and this collection framework, starting with the Array.
An array is not resizable. And I think that’s probably the biggest downfall of the Array is that you can’t change the size once it’s been created. An Array does store primitives and objects. So that’s nice. There’s flexibility there. It does have to be homogeneous, meaning that they’re all of the same type. Now, we saw that polymorphism is still okay with an Array, but it still has to be related. Everything has to be of the same type. An Array does have special notation, the square bracket notation, to access elements. And it does have a special syntax for initialization. I’m not sure that I’d say either of those are pros or cons. It’s just a notable difference.
Now, with the collection framework, most of the collections are dynamically sized, meaning that as you add to the collection, it will grow, and as you remove things from the collection, it will shrink. And so that’s really nice that we don’t have to worry as much about creating something and knowing what the size needs to be in advance and then having trouble dealing with any changes to that size. Now, it says here that collections only store objects, and that’s true. However, there is a way for us to get primitives into a collection. Essentially, we wrap the primitive with an object. We’ll talk a little bit about that in this section, but in the next section, we’ll talk about something called autoboxing, which really makes that transparent to us.
Collections can be heterogeneous. You can put anything that you want in a collection, but that’s not necessarily a good thing. If you get something in the collection that you weren’t expecting and it pops out and you call the wrong method on it, you’re going to get into trouble. Right? So there’s actually a syntax that’s been created called generics, and that helps us say, really, only a certain type of thing should get into this collection. So while collections can be heterogeneous, there’s been some movement and activity to reduce what it is, I guess reduce that flexibility, because it isn’t always beneficial. With collections, we’re dealing with just regular objects.
So when we want to access elements, when we want to remove elements, and so on, we just use methods on an object. There’s no special syntax, no square brackets, no curly braces for initialization. It’s just a regular object. There are two basic types in the collection framework. Both of these can be found in the Java Util package. The first is the collections framework. We’ll spend a little bit of time talking about lists and sets and cues. All of those belong to the collections. And then there are maps. And maps are like dictionaries or phone books or if you’ve ever worked with an associate of array. That kind of an idea. So there are two separate APIs. They’re both a part of the Java Util package. And we’ll examine both in this section.
- Collections
One of the best places to start when talking about the collection API is the array list. An array list is a lot like an array, but it’s dynamically resizable. Working with the array list is almost as easy as working with an array. So let’s take a look at the code. Here’s an example. So first of all, notice that we’re importing Java Util star. So this array list is in the Java Util package and we instantiate it just like we would any other object. So new array list. And once we have it, then we can just start adding values like hello and world here. We’re printing it out using the system out print line and we’re just passing the array list in. Here’s another example, same type of thing. We’re creating the array list.
We’re using the add method to add additional strings. So we’ve got Bruce Banner, Barry Allen, Bruce Wayne, Clark Kent, and then we’re printing it out again. So notice that we’re using print line to show the contents. And that’s what you’re seeing right here, a comma separated list of all the different names. And the reason that we’re getting this comma separated list with the brackets surrounding the entire list is because the collection API overrides the two string method. So we can pass in any collection, two string will be called and we’ll be able to see the contents of that collection, although it’s a little bit more common to iterate through the collection. Just know that this is a nice handy way to quickly see what do you have.
The other thing you might have noticed is that in the array list, we did not pass in a size. We can, by the way, you can pass in a size to say how big you think it will be, but you don’t have to. And so what happens is the array list will grow as we add stuff to it and it will shrink as we remove things. Each array list is going to keep track of the number of elements that it has. So if we want to find out how many elements are inside, we call a method. And that method is called size. It is not length and it’s not a property called length. So that’s one of the confusing parts when you’re learning arrays and array list, keeping all that straight. But with the array list, we use the method. And again, the method is called size.
And the size is going to be affected by adding and removing elements. Every time you add an element, the size will increase. Every time you remove it, it will decrease. There is a slight optimization that you can do, which is to set the initial size of the array list right in the constructor. Here’s an example. We’re setting this array list with an initial capacity of four. Now, that doesn’t mean it’s going to be stuck with four things. It’s just saying when you first create yourself plan on having four elements. But if it needs to grow, if it needs to shrink, it still can do that. Removing an element is pretty straightforward. There is a method here called remove and you pass in the object that you want to remove from that collection.
So after removing Barry Allen, if we print out the list now we just have Bruce Banner, Bruce Wayne and Clark Kent. If you’re curious of whether an array list has some content, you can use the contains method. So here’s a check to see if the list contains Gotham City. If it does, it’ll return true, if it doesn’t, it will return false. I should point out that the reason that this contains method works is because what it’s going to do is it’s going to call the equals method on the object that you pass in and it’s going to see if the object that’s been passed in is equal to anything in the list. If it is, then it will say true. And it’s the same thing for the remove method we just saw.
If I go back a slide here, list remove, what it’s going to do is it’s going to call the equals method to see if what we’ve passed in is equivalent to anything in the collection. And if it is, then it removes it. And that’s why it’s a really good idea to make sure that any kind of object that you think will be put in a collection overrides the equals method. And of course, what is the correlated rule? Anytime that you override equals, you also have to override hash code. Now why do we need hash code for collections? Well, later we’re going to see some hash collections like hash set and hash map, and they use that code to help find things in their collections. There’s another method called Clear which will empty everything out of the array list.
You can check to see if the array list is met empty by calling is empty. And what you’re going to find is that all the methods I’ve talked about so far are available to all of the collection framework objects. And that’s because they all implement the same interface, the collection interface. And what’s nice is that it makes it really easy to learn the collections because once you’ve learned one like array list, now you know how to use some of the other things like a set. And furthermore, that makes your code flexible because since the collections all work the same way, they can be easily replaced for one another. And where have we seen that concept before? Paul Amorphism? And collections take great advantage of this flexibility.
- The Collection Interface
So let’s take a look at that polymorphism. Let’s look at the collection interface and the collection hierarchy. Now I’m going to show you a diagram that’s incomplete, but it’s just showing you some of the more popular members of the collection class. So we’ll start here. At the top we’ve got the collection interface and most of the methods that we’re working with have been defined in here. There are three sub interfaces that extend the collection interface and add some additional methods that are helpful for specific data structures. There’s one for List, one for Set and one for Q. Now, these classes right here, these are abstract classes.
We’ve learned about abstract classes and the purpose of the abstract class is to provide default implementation of some of the stuff that is coming from the interfaces. In other words, let’s say that I wanted to make a list. Well, if I had to implement all the methods that are available in List and all the methods that are available in collection, that might be a lot of methods that maybe some reasonable defaults could have been made for me. And that’s really what these abstract classes do. So Abstract List provides default implementations for many of the methods and then what we can do with our own collection types is decide which ones do we want to override.
So the classes that we generally interact with are the ones in green. So our array list length list, hash set, tree set, array blocking queue, and of course, there’s others as well. And so the nice thing though is that when I’m using an array list, I’m treating it like a collection. I tend to use only the methods that are in the collection. And what that means is that I could swap out fairly easily a linked list for an array list or even a hash set for an array list and it would have more or less the same functionality. Now, we’re going to talk about the differences between lists, sets and queues in a little bit, but that’s the general idea. And this is what gives us all the polymorphism.
The fact that all of these five classes at the bottom array lists, linked list, hash set, and so on, that they all ultimately implement the collection interface. And it’s in the collection interface that we have methods like add, remove, contains size, is empty and clear. There’s also a way to turn a collection object into an array with a call to the two array method. And by the way, the arrays class has a way of turning an array into a list. They have a method called as list. So the two array method that ends up becoming important because there will be times where you’ll be calling into an API and that API is expecting an array. But you’ve been working with a collection. Well, just note that there is a way to fairly easily turn your collection into an array.
- Iterator
At some point when you have a collection, you’re going to want to iterate through it. And there’s an object that’s provided to us from the collection API called an iterator to do just that. It traverses in a way that’s similar to using a for loop. But it’s an object and it has methods. The iterator is defined in the Java util package. And the way that we get it is we call the Iterator method on our collection. So here’s an example. Let’s say I’ve got some kind of a list. What I can do is I can say list iterator and then that will return to me the iterator object and then we just put it in some kind of a loop. Now what we do is we ask the iterator if there’s any more objects.
And the way we do that is to say iter in this case iter has Next and it will return a boolean if there is another element. So if that’s true, we’ll then iterate through and to get the next object, you say iter next. So the iterator interface really only has three methods. We’ve got has Next which returns a boolean. There’s Next, which returns an object and then there’s remove, which will remove the current object. Now if you want to move back and forth rather than just forward, then you’re going to want a different kind of an object called a list iterator. So let’s just take a quick look at the iterator and the list iterator and see how that they work. First of all, when you do the lab, you’re going to see exactly what I’m showing you here.
In that you’re going to see a bunch of yellow, a bunch of warnings, yellow, underlines and so on. And the reason that we’re seeing that is it’s saying we don’t know what type this array list is. In fact, I’ll just show you what the error or the warning is. It just says array list is a raw type, references to generic type array list should be parameterized and we will talk all about that in the next section. So for right now, just know that yes, this is expected because we haven’t learned a certain type of a syntax and when we learn it, that will go away. So for the first lab, it’s okay to see all these warnings. After this section they will go away.
So with that said, how would I get an iterator from this? Well, you just have iterator I equals. And right from the array list itself, I can say languages iterator and then we have our loop and I can say while I has next. And then we can print out whatever the current value is, I dot next and it will go through and print out each of these languages. Let’s run it, just make sure it does what it says it’ll do. Sure enough, there it is. Java, swift JavaScript. Notice that arrayless it maintained the order that I put it in. That is a characteristic of a list, but we’ll talk more about that in an upcoming lecture. So that’s really all we can do with the iterator. We can do has next, we can get next.
I could remove something if I wanted to, but as I mentioned, if you want to go in both directions, if you want to do has next and then maybe has previous, you’re going to need a different kind of an iterator. And that’s called a list iterator. So what we do is we would say list iterator equals languages. List iterator. Now, one thing I want to point out is that a list iterator is only available for lists. So if we were dealing with some other kind of a collection, like a set, for example, this would not work. Once we have a list iterator, then we can do a whole bunch of stuff. So rather than just has next, we have has next, has previous. Or if we want to get the next object, we can set next, or we can just say previous. So we have a few more options when we have a list iterator.
- Lists
What we’re going to do now is go through the different types of collections. We’re not going to go through every collection, but we’ll go through the major types and the most popular ones of each type and we’re going to start right now with the list. So we’ve got our collection interface and it defines a bunch of methods for all of the different collection types. There is a sub interface and an interface that extends collection and that adds a few more methods for specifically lists. So lists have the following characteristics they maintain the order of the elements they contain, they allow duplicate entries for any given object and they can be manually sorted into any order that we’d like.
So they are ordered and there are a lot of options you have for lists. But the two most common would be array list, which we’ve already started to look at, and linked list. So since the lists are ordered, that means they also have an index and you can use that index for some of the methods that are part of the list interface. The list interface gives us methods to get set and remove elements by an index. So let’s look at a couple of those methods here’s using set, list set. Now, out of all the methods that are part of the collection and list interface, I think set was the one they misnamed. I think it would have been better called replace because that’s what you’re doing.
The way that set works is you give it the index and then you say specifically what you want the value to be. The problem is that you can only set things where something already exists. In other words, you can only replace things. For example, if there wasn’t anything in the second index element, then this list set two would fail. We can remove by index as well. So in this case we’re doing list remove one and remember that the index does start with zero. So we’re removing the second element here and that’s how lists work. In general, what’s the difference between an array list and a linked list? Well, an array list is really fast at random access.
So if I pass in an index, if I say list get 27, it can find that element very, very quickly. But if I start adding and removing elements in the middle, then array lists are a little slower and it’s because they actually have to physically move the elements to make space. So for example, if I’m adding an element here and I’m going to add it at index four, then we have to move all of the additional elements from five on down one and that takes some processing. And of course the same thing when we remove, we would have to shrink everything. So they’re slower at removing and adding things from the middle of the list, whereas link lists are pretty much the opposite.
They are a lot slower at getting by an index and they’re much faster at adding and removing elements. And the reason is because the way the length list works is that it’s not a set order of things in a specified space. It’s an object that refers to an object that refers to another object and so on. So if I need to add something in the middle, then look at what happens. First. What we have here on the left is our current length list structure. And now that we’re going to add something, all that we had to do was take what this second element was referring to and have it refer to the next or the new element that we’ve just added.
And then we have this new element refer to the one that the second one had been previously pointing to. So you can see that that’s a lot easier than trying to move everything down one. So that’s what you do. You just how am I using this data structure? If you need a collection that maintains order that allows duplicate objects, basically behaves like an array, but allows it to grow and shrink, then you choose a list. And then if you find that you’re doing a lot of adding and removing the middle, we’ll go with a linked list. Otherwise you’re probably going to want the array list.