Java 11 Developer Certification - List and ArrayList Other Methods

April 04, 2021

What we are covering in this lesson

  1. Other ArrayList methods
  2. add, addAll, set and get methods

Other ArrayList methods

Now lets look at the other methods as well. Below code contains most of the methods covered, from Comparision to Search to Data Manipulation to Data Transformation methods.

We have created three ArrayLists, and then calling the methods on these lists. Brief description of the used methods are as below.

  • isEmpty() - returns true if there are no elements in array
  • equals() - returns true if element values are equal
  • contains() - returns true if element values are equal
  • containsAll() - must find all elements in the list, order does not matter
  • indexOf - returns -1 if element not found or the index of element if found
  • lastIndexOf - returns -1 if element not found or the index of element if found
  • sublist - returns a reduced list, using starting index, and ending index
  • ListIterator - allows you to specify a starting index
package maxCode.online.list;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class ArrayListExamples {
	public static void main(String[] args) {
		ArrayList<String> firstArray = new ArrayList(List.of("ABC", "DEF", "GHI", "JKL", "MNO"));
		ArrayList<String> secondArray = new ArrayList(List.of("ABC", "DEF", "GHI", "JKL", "MNO"));
		ArrayList<String> thirdArray = new ArrayList<>();

		// isEmpty() returns true if there are no elements in array
		System.out.println("thirdArray.isEmpty() = " + thirdArray.isEmpty());

		// .equals() returns true if element values are equal
		System.out.println("firstArray.equals(secondArray)) = " + (firstArray.equals(secondArray)));
		System.out.println("firstArray.equals(thirdArray)) = " + (firstArray.equals(thirdArray)));

		// .contains() returns true if element values are equal
		System.out.println("firstArray.contains(\"DEF\")) = " + (firstArray.contains("DEF")));
		System.out.println("firstArray.contains(\"ZZZ\")) = " + (firstArray.contains("ZZZ")));

		// .containsAll() must find all elements in the list, order does not matter
		System.out.println("firstArray.containsAll(\"ABC,DEF\")) = " + (firstArray.containsAll(List.of("ABC", "DEF"))));
		System.out.println("firstArray.containsAll(\"DEF,ABC\")) = " + (firstArray.containsAll(List.of("DEF", "ABC"))));
		System.out.println("firstArray.containsAll(\"ZZZ,ABC\")) = " + (firstArray.containsAll(List.of("ZZZ", "ABC"))));

		// .indexOf returns -1 if element not found or the index of element if found
		System.out.println("firstArray.indexOf(\"DEF\")) = " + (firstArray.indexOf("DEF")));
		System.out.println("firstArray.indexOf(\"ZZZ\")) = " + (firstArray.indexOf("ZZZ")));

		// .lastIndexOf returns -1 if element not found or the index of element if found
		System.out.println("firstArray.lastIndexOf(\"DEF\")) = " + (firstArray.lastIndexOf("DEF")));
		System.out.println("firstArray.lastIndexOf(\"ZZZ\")) = " + (firstArray.lastIndexOf("ZZZ")));

		// sublist returns a reduced list, using starting index, and ending index
		System.out.println("firstArray.subList(2,4)) = " + (firstArray.subList(2, 4)));

		Iterator forwardIt = firstArray.iterator();
		while (forwardIt.hasNext()) {
			System.out.print(forwardIt.next() + " ");
		}

		// The ListIterator allows you to specify a starting index
		ListIterator traverseIt = firstArray.listIterator(2);
		if (traverseIt.hasNext())
			System.out.println("\ntraverseIt.next() = " + traverseIt.next());

		// Reset ListIterator for example
		traverseIt = firstArray.listIterator(2);
		if (traverseIt.hasPrevious()) {
			System.out.println("traverseIt.previous() = " + traverseIt.previous());
		}
	}
}
thirdArray.isEmpty() = true
firstArray.equals(secondArray)) = true
firstArray.equals(thirdArray)) = false
firstArray.contains("DEF")) = true
firstArray.contains("ZZZ")) = false
firstArray.containsAll("ABC,DEF")) = true
firstArray.containsAll("DEF,ABC")) = true
firstArray.containsAll("ZZZ,ABC")) = false
firstArray.indexOf("DEF")) = 1
firstArray.indexOf("ZZZ")) = -1
firstArray.lastIndexOf("DEF")) = 1
firstArray.lastIndexOf("ZZZ")) = -1
firstArray.subList(2,4)) = [GHI, JKL]
ABC DEF GHI JKL MNO 
traverseIt.next() = GHI
traverseIt.previous() = DEF

add, addAll, set and get methods

In this part, we will look at the simplest of ArrayList methods. Since these methods are very simple, one can easily overlook them, and so its necessary to have a look at it once!

We have the ArrayListExtras class, and one nested static BaseClass as well. In the main method, we create two arrayList, one raw and one types with the BaseClass type.

We added some instances of BaseClass to the typed ArrayList, and looped through it without needing any casting. And populated the raw list with its own copied of the BaseClass objects

The we again demonstrate the typed list needs no casting, whereas raw list does.

When we try the add and set method for index list.size(), its interesting to note that we get an exception for the set statement, and not the add statement.

So always remember that add, is really adding more elements, either appending to the list or inserting additional elements at a specified index. And set is changing the object being referenced at a particular index. So setting an object at an index past the list’s size will cause an error, and it did here.

Also, if you’re going to use the add method and exceed the index size, it can only be by one. So the line where we are trying to add at index list.size() + 1 will always throw a runtime error.

The we look at the addAll method, and with addAll if we use an index and want to add elements to the end of the list, we use the List.size(). And that’s equal to addAll with no index. And now in addition, we’re using the set method on our rawList to add the elements to the typedSubList.

Now the problem here, is we’ve got a compiler error on the typedList.set statement. Because we defined a type for this ArrayList, the compiler indicates that we’ve made an error and we’re trying to set something other than BaseClass into the list. Thats why we have commented it out. Looking at the output, notice that we didn’t actually insert elements at index zero, instead, we replaced the BaseClass object with our sub-typedList.

Then we have a set with newly instantiated lists. Now as you can see, this code compiles fine, but when I run it, we actually get an exception if we use set. And thats why we have replaced it with add. So you can see here, that just instantiating a list, even when setting capacity, doesn’t fill the list with any default elements, including NULL.

The last part we see what happens with subList, when we use it on the typed ArrayList. I’ve introduced an error on the last line. Because it’s a rawList returned, trying to access an object on the list, and not specifying a type, that results in a compiler error. In this case, you can see it’s trying to setName, you can’t resolve method setName in object, because of the type.

package maxCode.online.list;

import java.util.ArrayList;
import java.util.List;

public class ArrayListExtras {
	public static class BaseClass {
		private String name;

		BaseClass(String name) {
			this.name = name;
		}

		public String toString() {
			return name;
		}

		public void setName(String name) {
			this.name = name;
		}
	}

	public static void main(String[] args) {
		ArrayList<BaseClass> typedList = new ArrayList<>();
		ArrayList rawList = new ArrayList();

		// add without an index, adds element to end of list
		typedList.add(new BaseClass("abc"));

		// add with an index, adds element at the index
		typedList.add(0, new BaseClass("bcd"));
		typedList.add(0, new BaseClass("cde"));

		// Add elements to rawList, note that we can access all
		// elements in typedList as a BaseClass
		for (BaseClass b : typedList) {
			// We'll make copies of the BaseClass objects and add
			rawList.add(0, new BaseClass(b.toString()));
		}
		System.out.println("typedList = " + typedList);
		System.out.println("rawList = " + rawList);

		// Can do this in a typed list without casting.
		// setName() is method on BaseClass
		typedList.get(2).setName("ccc");

		// Trying same thing on object from raw ArrayList is a bit uglier
		((BaseClass) (rawList.get(0))).setName("aaa");

		// You can add an element at an index that is one larger than the number of elements
		typedList.add(typedList.size(), new BaseClass("def"));

		System.out.println("typedList = " + typedList);
		System.out.println("rawList = " + rawList);

		// You can add an element at an index that is one larger than the number of elements
		typedList.add(typedList.size(), new BaseClass("def"));

		// You cannot set an element at an index that is one larger than the number of elements
		// typedList.set(typedList.size(), new BaseClass("def"));
		// typedList.add(typedList.size() + 1, new BaseClass("def"));

		System.out.println("typedList = " + typedList);
		System.out.println("rawList = " + rawList);

		// Next, we create a typed List which we'll try to add to our
		// ArrayLists
		List<BaseClass> typedSubList = List.of(new BaseClass("efg"), new BaseClass("fgh"), new BaseClass("hij"));

		// You can add a collection at an index that is one larger than
		// the # of elements
		typedList.addAll(typedList.size(), typedSubList);

		// Typed ArrayList catches mistakes at compile time
		// set does not mean setAll
		// typedList.set(0, typedSubList);
		rawList.set(0, typedSubList);
		System.out.println("typedList = " + typedList);
		System.out.println("rawList = " + rawList);

		ArrayList<BaseClass> newBaseList = new ArrayList<>();
		newBaseList.add(0, new BaseClass("one"));

		ArrayList<BaseClass> newBaseListWithCapacity = new ArrayList<>(10);
		newBaseListWithCapacity.add(0, new BaseClass("one"));

		ArrayList<BaseClass> newBaseListWithSomeElements = new ArrayList<>(
				List.of(new BaseClass("one"), new BaseClass("two")));
		newBaseListWithSomeElements.add(2, new BaseClass("three"));

		// sublist can return a typed List if you specify it.
		List<BaseClass> typedSublist = typedList.subList(0, 2);
		typedSublist.get(0).setName("ABC");

		// or alternatively sublist returns a rawlist
		List rawSublist = typedList.subList(0, 2);
		// Is it really a raw list?
		// rawSublist.get(0).setName("ABC");
	}
}

Output

typedList = [cde, bcd, abc]
rawList = [abc, bcd, cde]
typedList = [cde, bcd, ccc, def]
rawList = [aaa, bcd, cde]
typedList = [cde, bcd, ccc, def, def]
rawList = [aaa, bcd, cde]
typedList = [cde, bcd, ccc, def, def, efg, fgh, hij]
rawList = [[efg, fgh, hij], bcd, cde]

So this section reviewed things that were really not out of the ordinary, but things that are ordinary and easy to overlook.

  • Be careful if you see methods that are similarly named to those on List, like setAll (not a method on List, but a method on the Arrays class).
  • Or methods that have the wrong number of parameters, such as indexOf, lastIndexOf methods with additional parameters (String usage not List usage).
  • Be careful to remember that using set(), with an index out of the range, will cause a runtime exception.

So finally we end the List and ArrayList topic here.

Next section we will look at Lambda Expressions.