Arrays and ArrayLists
The course is part of this learning path
This course covers the fundamentals of data structures specifically looking at the regular built-in arrays that Java provides as part of the language, as well as the ArrayList class, which lives in the java.util package.
- Beginner coders or anyone new to Java
- Experienced Java programmers who want to maintain their Java knowledge
- Developers looking to upskill for a project or career change
- College students and anyone else studying Java
This is a beginner-level course and can be taken by anyone with an interest in learning about Java.
We discussed ArrayLists in the last lecture, which are a type of data structure that are like arrays but resized to accommodate the elements living inside them. However, one glaring limitation we discovered is that ArrayLists only work with reference types. They can't hold both primitives and reference types like regular arrays do. So, it seems like we're trading one limitation for another. But not to worry because we have a way of overcoming this issue. You see, an ArrayList is a type of entity known as a generic. This is evident by the angle braces that we used with it. Generics allow developers to create classes, code the class once, and make them work for a wide variety of reference types without the need to write the class over and over again with different types if the behavior is to be the same. The drawback is that the types have to be reference types, as we've discussed. So, what about primitives?
In come our heroes, the wrapper classes. That's wrapper with a w like wrapping a gift, not rapper like quick speaking lyricist. There are eight wrapper classes. Can you think of something else in Java that we have eight of that might be pertinent to the conversation? That's right. We have eight primitive data types. And the eight wrapper classes are, of course, reference types and correspond to each of the primitive types. So, as you see, the wrapper classes are Byte, Short, Integer, Long, Float, Double, Character, and Boolean. So, except for integer and Character which are spelled out fully, the wrapper classes are all just capitalized versions of their primitive counterparts. Pretty cool. So, how do these help us overcome the limitations of generics like ArrayLists being able to only work with reference types? Let's create a file called WrapperFun. All right, so over here, New, Java class, we have WrapperFun. And I'm going to put this down here a little bit. And we need to import java.util.ArrayList. And then we have our public static void main. Here we go.
And we'll make an ArrayList, and we're going to need an ArrayList of integers, but this time we have to use the wrapper class type, which is a reference type. So, ArrayList, there we go. And how do we add integers? Let's just do to just to keep it pretty simple. Now you might think, hey, here's a good way to do it. But you'll see the compiler will even tell us that's not the best way to do it. We'll talk about that. But let's see if it works first, int i = 0; i < myAL.size(). Remember, size method instead of the length field, public field or property. Here we go. And System.out.println (myAL.get(i)). Here we go. We'll discuss the warning again, this one right here, in more detail in just a minute. For now, let's run it.
So, WrapperFun, right click, 'Run' it. And we do in fact, get our 10 and our 22. Pretty cool. So, we seem to have a way of overcoming our issue with ArrayList where we can only hold references. But what's the deal with this warning? The issue is that this seems to be what we would expect to do. Wrapper classes are reference types, and to create them dynamically, we used the new keyword. So, we can do that, but wrapper classes are special. To make our lives easier, Java automatically performs the placing of the primitives that we want to store inside of the object for us in a process called autoboxing or automatic boxing. The primitive is automatically put into our box here, an object of the type of the corresponding wrapper class for us.
So, we can treat objects of the wrapper class just like their corresponding primitives in this situation without too much extra code. So, instead of doing this, notice if I have this line here and it just crosses out the integer right there, and the little bubble here says Remove boxing, so we could do that. But I'm just going to change it manually. Here we go. 10 and 22, and no more complaints. So, even though this is a primitive that we're storing in here, it automatically knows that since it only holds references, it's going to create an automatic box for this. And this only works with the wrapper classes. And let's run it again and see if it still works. Right click, 'Run', and there you go. Got the two values again one more time. So, you may have also noticed that when we use the get method, we don't need to convert that back. We don't need to say like dot two integer, or get me integer, or something like that. It automatically prints,
everything is fine. And this value is actually automatically unboxed. We can actually see even more clearly. So, int num = myAL.get(i). If we wanted to, we could use num instead. See, no error. And that's because even though this technically would return a reference, it knows that the thing on the left expects there to be a primitive, so it returns a primitive. So, that's pretty cool. So, that's auto unboxing. Besides opening up the ability to work with primitives in the context of generics like ArrayList, wrapper classes also provide a lot of very powerful and useful static methods, which means that they can be called directly on the class type. We'll talk a lot more about static methods later in the course. But for now, again, all you have to note is that we are calling the method directly on the class name rather than creating an object and then calling the method on the object. So, let's test one of these out near the bottom of our wrapper class. So, I'm going to actually just go under this loop here. And we'll write our additional code, someValue =, now notice I'm putting 450 in double quotes there. And then, if I want to get the numeric value out of this, and again, this is a trivial example but it gives the information about how to do it. So, you just say integer which is a wrapper class for the ints.parseInt, and then you pass it a string and it will return an int. Pretty cool.
So, numeric value, I can manipulate it just like any other integer, and then print it out. So, what we should do, what we should have is 460 now. So, let's run it and see what it does. Right click, 'Run', and you'll see that now in addition to the other two inside that ArrayList earlier, we now have our 460. Because we were able to convert this string to this number. And that's it, that may not seem very important, but a lot of data that comes into our programs comes in text versions of data. And we have to convert it to numeric versions in order to manipulate it in a numeric way. Otherwise, it would think something like plus equals as concatenation, not adding. So, we sometimes need to convert it to a numeric type to work with it. So, as you can see, again the call to parseInt on someValue converts the string into an integer and returns the integer value. We can then manipulate the numericValue as we would any integer variable. In our example, we just added 10 to it. Before moving on, I have a challenge for you. Continuing with our wrapper class Fun or WrapperFun example, below the parseInt code that we've just added, I'd like you to create another string, but this time to hold a double value. That is, a value with a decimal point in it, like an approximate value for Pi, 3.14159.
Use the appropriate wrapper class to convert that string containing a double representation into an actual double, and then print that actual double out. You can use your intuition to guess what you might need to do. And maybe the hint that Integer.parseInt has, that's one thing to do when you have integers is Integer.parseInt. So, maybe the double wrapper class could help you somehow. Maybe look into that. So, pause the video, come back when you're done, or if you need some help. How did that work out for you? If you struggled with that one, that's okay. I gave you hints, but expected you to use some inference and maybe the automatic completion features in IntelliJ or your IDE of choice to help you out. Let's write the code. So, underneath all this stuff, we're going to add, String strPi is what I'm going to call it, and we'll put 3.14159.
You could have picked a different double value. That's fine, double myPi = Double.parseDouble. So, Integer.parseInt, Double.parseDouble. And we're passing it in this strPi here. And we're going to do System.out.println on myPi. Very good. Now, let's run it and see what we get. So, in addition to the three values that we had, let's see what happens. So, we run it. And we get the value 3.14159. Now, printing doesn't really give you a perfect idea of what's happening.
So, if you want to add to it or try something else, 2.5, and just see what that does. You can see that you can do math with it. So, you can see very clearly that it's actually a number and not just a string. So, it works exactly as we expected. Now, you know a little bit about how to work with the wrapper classes both in the context of generics like the ArrayList and also to use their static methods like parseInt and parseDouble. So, next up, we have our first programming project for this section. You will be challenged to work a little more with regular arrays. I'll see you there.
John has a Ph.D. in Computer Science and is a professional software engineer and consultant, as well as a computer science university professor and department chair.