• 15 hours
  • Easy

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 3/28/24

Manage complexity with the right collection

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.

A special seat for a special one
A special seat for a special VIP

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:

  1.  The type of the elements the array will contain, followed by [].

  2. 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:

Declare a variable and create an array in one statement
Declare a variable and create an array in one statement

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.

adorable squirrel
This one deserves a spot at the top

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:

  1. Declare a variable whose type is the List interface. That means you can assign any object to the variable that puts in place the List interface, including the ArrayList class.

  2. Initialize the variable with an expression starting with the new keyword that creates an instance of the ArrayList class.

This can be done in one line with the following syntax:

declare an array list
List declaration and initialization
  1. The declaration takes place before the = assignment operator. First, you have the type, which is List. 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.

  2. The actual creation takes place with the  new ArrayList<Integer>()  expression. The initialized object is assigned the  myList 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 of boolean if you want to store true/false values.

  • Float instead of float 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]
  1. The first statement creates an empty list named myList.

  2. 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.

  3. 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 your List 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:

Declaring a Set
Declaring a set

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:

Dictionary elements
Dictionary elements

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:

Declaring a dictionary in Java
Declaring a dictionary in Java

The main difference, compared to lists and set, is that you parametrize your dictionary with two elements, using the <String, Integer> syntax.

  1. String is the type for the key

  2. Integer 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 the myMap 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."

  1. You can add a value with a put() method with two arguments: the key and the value.

  2. 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.

Example of certificate of achievement
Example of certificate of achievement