Imagine you are the communication manager of a fashionable theater. One of your main responsibilities is to manage the front row, which means making sure that the artists' relatives and friends, as well as other VIPs, get the best view of the show.
If all you had to do was handle two invitations for the main artist, you could imagine using just two variables holding the guest's name. The Java code would look like this:
// Declare a variable for each guest in the front row
String frontRowGuest1;
String frontRowGuest2;
Then, when the performer gives you the information, you would just assign a name to each variable. For instance, you would have:
// Assign the guest names
frontRowGuest1="Mary Poppins";
frontRowGuest2="Jane banks";
If the front row has 30 seats, wouldn't it be easier if you could use just one variable that would contain all that information?
Lucky you! Java offers a data structure capable of holding a fixed number of values of a single type. This structure is called an array. Let's see when and how to use one.
Use an array to store a fixed number of elements
An array is a numerically ordered list of same type elements. Each element is associated with a number called an index. Indexing starts with 0 (not 1!), meaning that the first element is associated with an index 0, the second with 1, etc.
Declaring an array uses the same syntax as for any variable. You provide:
The type of the elements the array will contain, followed by
[]
.The variable name, which clearly expresses the intent of the array.
For instance, to store the number of cups of coffee you drink each day of the week, you can declare an array of integers with the following syntax:
// Declare the variable
int[] cupsOfCoffeePerDayOfTheWeek;
Then create the actual array with a length of seven (How many days are there in a week?) and initialize the array with it:
// Create the array and assign it to the variable
cupsOfCoffeePerDayOfTheWeek=new int[7];
When the array is created, each element is initialized with the default value of the type of the array. In the case of an array of int
, that means 0.
You can also declare and create an array at the same time. Here is what you would do to declare a variable and initialize it directly with a new array of three int
:
Getting back to our weekly coffee management: now that the array is created, you can perform two operations on it:
1. Access a value at a given index
2. Set a new value at a given index
In both cases, you use the name of the variable followed by [
, the value of the index, and ]
.
For instance, if you drink three coffees on the fifth day of the week, you can write:
// Assign the value 3 to the fifth day of the week
// That's index 4, since the first index is 0
cupsOfCoffeePerDayOfTheWeek[4]=3;
To print the number of coffees you drink on the first day of the week, you can write the following statement:
//Print the number of coffees on the first day of the week
System.out.println(cupsOfCoffeePerDayOfTheWeek[0]);
Finally, if you want to set all the values at the same time, you can either:
Set all the values at the time of creation of the array
Use a loop that sets each value, one by one
Loops will be covered in the next part of the course. For now, let's create a new array and assign it to the cupsOfCoffeePerDayOfTheWeek
variable:
//Create a new array with all the values and assign it to our variable
cupsOfCoffeePerDayOfTheWeek=new int[]{6,2,3,7,3,4,1};
Arrays are efficient and great if you manage a fixed number of elements. In practice, you often have to deal with a varying number of elements. Java makes it easy to deal with those cases with collections. Let's start with the most popular of them, the list.
Use lists when the number of elements is not fixed
Arrays are well and good, but they have limitations:
They have a fixed size
You can only change the existing values
Let's say you wanted to list animals in order of their cuteness, and you start off will a small array of four items: fox, owl, koala, and otter. Now, let's say you want to add a squirrel and put it between the fox and the owl.
With an array, you can't insert an additional item, you can only replace items. You also cannot add (in programming speak: append) your squirrel to the end of the list. To accommodate it, you'd have to create a whole new array with five spots instead of four. Then you'd have to add all your elements again by hand. That sounds pretty long and boring, right?
That's where an ordered list comes in! As they are mutable, you can modify the contents and the number of a given collection of elements. After arrays, this feels magical! ✨
Among other things, lists allow you to:
Access each element by its index.
Append (add) a new element to the end.
Insert a new element at a specific index.
Remove an element at a specific index.
Very useful! In Java, there are several classes that use lists. You could even create your own! What's important is that the class you choose uses the List
interface.
In the rest of this chapter, we will use the ArrayList
class, which is the most common. Let's see how this works in practice!
Create a list and add elements
To create a list, you need to:
Declare a variable whose type is the
List
interface. That means you can assign any object to the variable that puts in place theList
interface, including theArrayList
class.Initialize the variable with an expression starting with the
new
keyword that creates an instance of theArrayList
class.
This can be done in one line with the following syntax:
The declaration takes place before the
=
assignment operator. First, you have the type, which isList
. It is directly followed by<Integer>
, which is the type parameter for the list. A type parameter constrains the type of objects that can be stored inside the list. In this example, you will only be able to store whole numbers.The actual creation takes place with the
new ArrayList<Integer>()
expression. The initialized object is assigned themyList
variable.
You may have noticed that Integer
is spelled out and capitalized. That's because a list can only store objects, not primitive types. In the same way, you will need to use:
Double
instead ofdouble
if you want to store decimals.Boolean
instead ofboolean
if you want to store true/false values.Float
instead offloat
if you really insist on using them.
But what about the stuff we want to put in our list?
Great question! You can only create an empty list in Java. To put in elements, you have to add them one by one, like this:
List<Integer> myList = new ArrayList<Integer>();
myList.add(7);
myList.add(5); //-> [7,5]
The first statement creates an empty list named
myList
.You then add a first element with the
mylist.add(7)
statement. Java automatically boxes the value into an Integer object and adds it to the list at the 0 index.Finally, the
myList.add(5)
statement creates an instance of the Integer class with a value of 5 and adds it to the list at index 1.
Now, what's going on with that .add()
? In Java, adding, modifying, or removing elements requires using something called a method, and you guessed, .add()
is one! At this point, all you need to know about methods is that they let you do things. 😎
For the List
interface, there are three methods that are put in place by the ArrayList
class that come in handy:
add
- to add a new element at the end of an array. Here you need to provide a new element. You can also insert a new element at a given position by specifying the index before the value. For instance,myList.add(1,12)
will insert an integer with value 12 at position 1 and move the existing value at position 2, and so on.set
- to replace a new element at a specific index. Here you need to provide a new element and the index at which you want a new value to be positioned.remove
- to delete an existing element at a specific index. Here you need to provide the index of element you wish to remove. If you no longer need the first element, you can remove it from position 0. That will shift the original second element from position 1 to position 0, the third from position 2 to position 1, and so on.
Now, what does that look like? Here's the Java syntax for the above:
List<Integer> myList = new ArrayList<Integer>(); // -> []
myList.add(7); // -> [7]
myList.add(5); //-> [7, 5]
myList.add(1,12); //-> [7, 12, 5]
myList.set(0,4); // -> [4, 12, 5]
myList.remove(1); // removed 12 -> [4, 5]
Let's break this down, shall we?
You can see the same operation from before: adding 7, then 5 to the list.
Then you insert
12
at index 1. The existing value at index 1 is moved to index 2.Next, with
.set()
, the first number refers to the index, and the second gives the value you want to put there. In other words, you're asking yourList
to change the value at index 0. This will transform the original value, 7, to the new value, 4.Finally, with
.remove()
, you're asking your list to remove whatever value is found at index 1. That means you're asking it to get rid of 12.
This leaves you with your final list containing two integers: 4 and 5. Imagine doing that with fixed-sized arrays!
Keep track of the number of elements in your list
There is a very important method to use with a list, size()
, which allows you to get the number of elements in a list:
List<Integer> myList = new ArrayList<Integer>();
myList.add(1); // ->[1]
myList.add(2); //-> [1,2]
System.out.println(myList.size()); // -> 2
This makes it a lot easier to keep track of the placement of elements in your list.
The size()
method is extremely used, notably when you need to loop over a list. We'll get to this in chapter 3 of the next part.
Unordered collection - sets
A set is a collection of unordered unique elements. You'd use them when you don't care about the order - like a list of ingredients for a recipe. 🥑🌶🥕🌽🍅🍳
Declaring sets
Like with lists, Java has different classes to manage sets. We will focus on the most commonly used, the HashSet
.
Let's see the Java code:
As you can see, it's pretty similar to working with an ArrayList
. You first declare the variable with the Set
interface, and initialize it with an instance of the concrete HashSet
class.
Manipulating set elements
Here are the frequently used operations you can use with sets:
Add a new element with a new key
Remove an element for a specific key
Count the number of elements in the set
What about accessing an element?
Since sets are unordered collections, there's no simple way to point at particular elements - at least not like the ones you've seen so far. There are ways of doing this, but you'll learn more about them as you expand your knowledge of programming.
To add a new element, use add()
:
Set<String> ingredients = new HashSet<String>();
ingredients.add("eggs");
ingredients.add("sugar");
ingredients.add("butter");
ingredients.add("salt");
Since sets are unordered, using append or inserting elements at a specific point isn't necessary. All you do is add!
To remove an element, you use remove()
:
Set<String> ingredients = new HashSet<>();
ingredients.add("salt"); //adds salt to ingredients
ingredients.remove("salt"); //removes salt from ingredients
The trick is that you must provide the exact element to remove. Here you're getting rid of "salt."
Sets, like lists, also have the size()
method to get the number of elements in a set:
System.out.println(ingredients.size());
Maps - dictionaries
To recap from the video, a dictionary is a list of elements organized by a key. This key is a specific term you look up to find its definition or its value. This is called a KEY <> VALUE association.
For example, if you need to store your friends and their ages, dictionaries are the right collection to use:
All keys in a dictionary must be unique. It's like how only one person can sit on a chair at a time.
Declaring dictionaries
As for lists and sets, Java provides several classes to manipulate dictionaries. Each of these classes abides by the Map
interface, for which you can see the extensive documentation on the Java Tutorials website.
For this section, we will use the most common, HashMap
class. Here is the code to declare and initialize an instance of that class:
The main difference, compared to lists and set, is that you parametrize your dictionary with two elements, using the <String, Integer> syntax.
String
is the type for the keyInteger
is the type for the value
To add items to your dictionary, use the method myMap.put()
. In the parentheses, indicate first the key, then the value:
// my friends' ages
myMap.put("Jenny", 34);
myMap.put("Livia", 28);
myMap.put("Paul", 31);
System.out.println(myMap.get("Jenny")); // -> 34
In the last line, we've asked the program to print out the value for the key, Jenny. In this code:
The
System.out.println()
method prints the result of an expression that is provided between its parenthesis.The actual expression,
myMap.get("Jenny")
, returns the value identified by the key "Jenny," that is stored in themyMap
variable.
While using strings as keys, remember that such keys are case sensitive. For example, "Jenny" and "jenny" are two different keys that will associate with two different elements in a dictionary. For example:
myMap.put("Jenny", 34);
myMap.put("Livia", 28);
myMap.put("Paul", 31);
myMap.put("jenny", 21);
System.out.println(myMap.get("Jenny")); // -> 34
System.out.println(myMap.get("jenny")); // -> 21
One of the tricks to protect against such situations is using constants to specify the keys once and then reusing them throughout the code:
// define keys as constants
private static final String kJenny = "Jenny";
private static final String kLivia = "Livia";
private static final String kPaul = "Paul";
// use constants as keys
myMap.put(kJenny, 34);
myMap.put(kLivia, 28);
myMap.put(kPaul, 31);
// access an element4
System.out.println(myMap.get(kJenny)); // -> 34
You can see you have to use the private static final
keywords here to indicate that you need your strings to be constants and not variables. This is very useful as it guarantees that you keep your keys forever and will not lose any data by accidentally changing the key strings!
A little more about keys
While the most commonly used type is String
, keys in Java can be of various types, for example Integer
:
morning.put(1, "Wake up");
Just like for simple variable types and arrays, the same rules apply to dictionaries: it always has a type that cannot be changed. All values in a dictionary must be of the same type. And all keys must be of the same type:
myMap.put(kJenny, 34);
myMap.put(kLivia, 28); // Ok
myMap.put("Paul", "Designer"); // Error
Manipulating dictionary elements
Here are the frequently used operations you can do with dictionaries:
Access the value of an element by its key
Add a new element with a new key and value
Remove an element for a specific key
Let's imagine a dictionary of people's names and their jobs, called "professions."
You can add a value with a
put()
method with two arguments: the key and the value.To access a value, simply use the
get()
method with the key as an argument.
Let's check it out:
professions.put("Jenny", "Business owner");
System.out.println(professions.get("Jenny")); // -> Business Owner
You can also modify an element by reusing an existing key with the put()
method:
professions.put("Jenny", "Business owner");
System.out.println(professions.get("Jenny")); // -> Business Owner
professions.put("Jenny", "Developer");
System.out.println(professions.get("Jenny")); // -> Developer
Finally, to remove an element you can use a remove()
method with the key of the element you want to go:
professions.remove("Jenny");
Counting elements
Dictionaries, like lists and sets, also have the size()
property to get the number of elements in dictionaries:
System.out.println(professions.size());
Summary
In this chapter, you've learned the basics of working with containers that store multiple elements of a given data type:
Fixed-size containers: Arrays- elements of an array are indexed from 0 up and can be accessed using that index. The number of elements cannot be changed.
Ordered lists: Lists - elements of a list behave like an array. The number of elements can evolve by adding and removing elements.
Unordered lists: Sets- elements of a set are stored without a particular order and can be accessed by enumerating them.
Dictionaries: Maps - elements of a dictionary are organized by key-value pairs and can be accessed using a key.
The most common actions performed with collections are:
Access an element
Add a new element
Remove an element
Modify an element
Count all elements
Browse all elements
Which of the collections you choose depends on the task at hand. As you progress with your career, you'll be able to identify the best suitable type to use.