ZOFTINO.COM android and web dev tutorials

Java List Tutorial

List is an ordered collection. It can contain null values and duplicate elements. It allows for accessing elements using their index or position. In addition to iterator defined in collection interface, List provides special iterator called ListIterator which allows bidirectional access of elements and element insertion and replacement. Using generics, strong type safety can be enforced.

Implementations of List are AbstractList, ArrayList, Vector, Stack, AbstractSequentialList and LinkedList.

Table of Contents

List Hierarchy

java list hierarchy

ArrayList

ArrayList is a resizable array implementation of List interface. It implements all operations defined in List. It allows null values. ArrayList can be instantiated by passing internal array size to its constructor. If no argument constructor is used, array size will be set to 10. You can create array list from another collection object like set by passing it to array list constructor.

	//instantiate ArrayList with internal array size 10
	List<Integer> list = new ArrayList<>();
	//instantiate ArrayList with internal array size 20
	List<Integer> listOne = new ArrayList<>(20);
	//instantiate ArrayList from collection
	
	Set<String> set = new HashSet<>();
	set.add("hp");
	set.add("dell");
	set.add("sony");
	List<String> listTwo = new ArrayList<>(set);

ArrayList’s internal array capacity can be increased after its creation using ensureCapactity method. Internal array capacity of array list can be trimmed to number of elements it contains (it’s size) by calling trimToSize method.

	ArrayList<Integer> alist = new ArrayList<>();
	alist.ensureCapacity(33);

Elements can be added to array list by calling add method and passing value to it. The following example and output shows that array list maintains the order of elements in which they are added to it.

	List<Integer> marks = new ArrayList<>();
	marks.add(98);
	marks.add(34);
	marks.add(58);
	marks.add(87);
	marks.add(76);
	
	System.out.println(marks);

Output

[98, 34, 58, 87, 76]

An element can be inserted between element in array list by calling add method and passing index and element to it.

	System.out.println("before insert"+marks);		
	marks.add(3, 99);		
	System.out.println("after insert"+marks);

Output

before insert[98, 34, 58, 87, 76]
after insert[98, 34, 58, 99, 87, 76]

Adding and Inserting Collection to List

A collection like set can be appended or inserted to list using add method passing collection for appending or collection and index for inserting as arguments to it.

	List<String> playmentType = new ArrayList<>();
	
	playmentType.add("visa");
	playmentType.add("master");
	System.out.println(playmentType);
	
	Set<String> paySet = new HashSet<>();
	paySet.add("net bank");
	paySet.add("pay pal");

	playmentType.addAll(paySet);
	System.out.println("after appending collection: "+playmentType);	
	
	Set<String> paySetNew = new HashSet<>();
	paySetNew.add("discover");
	paySetNew.add("am expess");
	
	playmentType.addAll(1, paySetNew);
	System.out.println("after inserting collection: "+playmentType);

Output

[visa, master]
after appending collection: [visa, master, net bank, pay pal]
after inserting collection: 
[visa, discover, am expess, master, net bank, pay pal]

Getting Element by Index

You can get elements by their position using get method and passing index to it.

	List<String> device = new ArrayList<>();
	device.add("mobile");
	device.add("tab");
	device.add("laptop");
	
	System.out.println("element at index one: "+device.get(1));

Output

element at index one: tab

ArrayList Common Methods

You can use contains method to check whether an element exists in array list or not. An index or last index of an element can be obtained by calling indexOf or lastIndexOf method respectively and passing element to it. Emptiness of array list can be determined using isEmpty method. To know the number of elements array list contains, you can use size method.

	List<String> device = new ArrayList<>();
	device.add("mobile");
	device.add("tab");
	device.add("tab");
	device.add("laptop");
	device.add("desktop");
	
	if(device.contains("tab")) {
		System.out.println("list contains tab elemennt");
	}
	
	System.out.println("index of desktop: "+device.indexOf("desktop"));
	System.out.println("last index of tab: "+device.lastIndexOf("tab"));
	
	if(!device.isEmpty()) {
		System.out.println("array list is not empty");
	}
	
	System.out.println("size of array list: "+device.size());

Output

list contains tab elemennt
index of desktop: 4
last index of tab: 2
array list is not empty
size of array list: 5
element at index one: laptop

Removing Elements

An element can be removed from a list using remove() method and passing either element or index as an argument to it.

	List<String> fashion = new ArrayList<>();
	fashion.add("tshirt");
	fashion.add("polo");
	fashion.add("jeans");
	fashion.add("shirt");
	
	System.out.println(fashion);
	
	//remove by index
	fashion.remove(2);
	System.out.println("after remove by index \n"+fashion);
	
	//remove by element
	fashion.remove("shirt");
	System.out.println("after remove by element \n"+fashion);

Output

[tshirt, polo, jeans, shirt]
after remove by index 
[tshirt, polo, shirt]
after remove by element 
[tshirt, polo]

You can remove all elements from list using clear method.

	fashion.clear();
	System.out.println("after clear "+fashion);

Output

after clear []

Collection of elements can be removed from a list using removeAll method by passing to it a collection containing the elements to be removed.

	List<String> fashion = new ArrayList<>();
	fashion.add("tshirt");
	fashion.add("polo");
	fashion.add("jeans");
	fashion.add("shirt");
	
	System.out.println("before remove all: "+fashion);
	
	List<String> removeFashion = new ArrayList<>();
	removeFashion.add("polo");
	removeFashion.add("jeans");
	
	fashion.removeAll(removeFashion);
	
	System.out.println("after remove all: "+fashion);

Output

before remove all: [tshirt, polo, jeans, shirt]
after remove all: [tshirt, shirt]

ArrayList RemoveIf Example

Method removeIf executes a predicate (boolean valued function) for each element, if predicate returns true for an element, that will be removed from the list.

	List<Integer> discount = new ArrayList<>();		
	discount.add(80);
	discount.add(50);
	discount.add(20);
	discount.add(70);
	discount.add(30);
	
	System.out.println(discount);
	
	//remove discounts less than 50%
	discount.removeIf(i -> {
		if(i < 50) {
			return true;
		}else {
			return false;
		}
		
	});
	
	System.out.println("after removeIf: "+discount);

Output

[80, 50, 20, 70, 30]
after removeIf: [80, 50, 70]

List ReplaceAll Example

Method replaceAll() applies UnaryOperator (function which returns the same type as its input) on each element which is replaced with the returned value of the function.

	List<Integer> taxAmount = new ArrayList<>();		
	taxAmount.add(830);
	taxAmount.add(450);
	taxAmount.add(620);
	taxAmount.add(170);
	
	System.out.println("before replaceAll: "+taxAmount);
	
	//replace each value with new value 
	//calculated by the function
	taxAmount.replaceAll(i -> {
		return i*90/100;
	});
	
	System.out.println("after replaceAll: "+taxAmount);

Output

before replaceAll: [830, 450, 620, 170]
after replaceAll: [747, 405, 558, 153]

List RetainAll Example

Method retainAll removes all elements except the ones exist in the given collection.

	List<String> categories = new ArrayList<>();
	categories.add("appliance");
	categories.add("home");
	categories.add("travel");
	categories.add("food");
	System.out.println(categories);
	
	Set<String> retainCats = new HashSet<>();
	retainCats.add("home");
	retainCats.add("food");
	
	categories.retainAll(retainCats);
	System.out.println("after retainAll: "+categories);	

Output

[appliance, home, travel, food]
after retainAll: [home, food]

ListIterator Example

Using ListIterator, elements of a list can be traversed in backward and forward directions. It allows operations such as insert, remove and replace elements by providing add, remove and set methods respectively. It provides methods for traversing such as hasNext, hasPrevious, next, previous, nextIndex and previousIndex.

	List<String> cats = new ArrayList<>();
	cats.add("appliance");
	cats.add("home");
	cats.add("electronics");
	
	ListIterator<String> listIterator = cats.listIterator();
	System.out.println("forward iterator");
	while(listIterator.hasNext()) {
		System.out.println(listIterator.next());
	}
	System.out.println("backward iterator");
	while(listIterator.hasPrevious()) {
		System.out.println(listIterator.previous());
	}
	
	while(listIterator.hasNext()) {
		listIterator.next();
		if(listIterator.nextIndex() == 2) {
			listIterator.set("furniture");
		}
	}
	System.out.println("list after set "+cats);
	
	listIterator = cats.listIterator();
	while(listIterator.hasNext()) {
		listIterator.next();
		if(listIterator.nextIndex() == 1) {
			listIterator.add("kitchen");
		}
	}
	
	System.out.println("list after add and remove "+cats);

Output

forward iterator
appliance
home
electronics
backward iterator
electronics
home
appliance
list after set [appliance, furniture, electronics]
list after add and remove [appliance, kitchen, furniture, electronics]

When iterating over list using iterator or list iterator object, if other threads modify the list, it will throw ConcurrentModificationException. This behavior of iterator is called fail-fast. To fix this issue in multi threading environment, you can use synchronized block or handle the exception and recreate iterator object.

	List<Integer> lst = new ArrayList<>();
	List<Integer> synchronizedLst = Collections.synchronizedList(lst);
	
	synchronizedLst.add(45);
	synchronizedLst.add(49);
	
	ListIterator<Integer> li = synchronizedLst.listIterator();
	
	new Thread(new Runnable() {
		@Override
		public void run() {
			for(int i = 0; i<15; i++) {
				synchronizedLst.add(i+33);
			}				
		}			
	}).start();
	
	synchronized(synchronizedLst) {			
		while(li.hasNext()) {
			System.out.println(li.next());
		}
	}

Sub List

You can use subList method to get a view of the portion of the list by passing from index and to index to it.

	List<Integer> list = new ArrayList<>();		
	list.add(40);
	list.add(45);
	list.add(62);
	list.add(49);
	list.add(96);
	
	System.out.println("list "+list);
	System.out.println("list "+list.subList(2, 4));

Output

list [40, 45, 62, 49, 96]
list [62, 49]

Sorting List

The list can be sorted by using sort method according to the comparator passed to it.

	List<String> offer = new ArrayList<>();
	offer.add("flat 40% off coupon");
	offer.add("2% cashback on fashion");
	offer.add("20% off coupon on bags");
	offer.add("upto 40% off cashback");

	System.out.println("before sorting \n"+offer);
	//sort by keeping cashback offers first then coupons
	offer.sort((s, ss) -> {
		if(s.contains("coupon")) {
			return 1;
		}else {
			return -1;
		}
	});
	System.out.println("after sorting \n"+offer);

Output

before sorting 
[flat 40% off coupon, 2% cashback on fashion,
 20% off coupon on bags, upto 40% off cashback]
after sorting 
[upto 40% off cashback, 2% cashback on fashion,
 flat 40% off coupon, 20% off coupon on bags]

List Spliterator Example

Using spliterator object which can be obtained by calling spliterator method on the list, you can concurrently process elements by splitting it to into multiple spliterator objects using trySplit() method. Then performing an action on each element by calling forEachRemaining method on each spliterator object.

	List<String> stores = new ArrayList<>();
	stores.add("amazon");
	stores.add("ebay");
	stores.add("walmark");
	stores.add("itsy");

	Spliterator<String> spliterator = stores.spliterator();
	Spliterator<String> spliteratorSec = spliterator.trySplit();

	new Thread(new Runnable() {
		@Override
		public void run() {
			spliterator.forEachRemaining(s -> {
				//get coupons for store from remote host
				int tid = (int) Thread.currentThread().getId();
				System.out.println("thread "+tid+" getting coupons "+s);
			});
		}
	}).start();

	spliteratorSec.forEachRemaining(s -> {
		//get coupons for store from remote host
		int tid = (int) Thread.currentThread().getId();
		System.out.println("thread "+tid+" getting coupons "+s);
	});

	try {
		Thread.sleep(500);
	} catch (InterruptedException e) {}

Output

thread 10 getting coupons walmark
thread 1 getting coupons amazon
thread 10 getting coupons itsy
thread 1 getting coupons ebay

LinkedList

LinkedList implements List and Deque interface. Since LinkedList is doubly linked, elements can be added to and removed from both ends. It allows bi directional element traversal.

You can insert an element at the beginning of the list using addFirst or offerFirst method.

	LinkedList<Integer> linkedList = new LinkedList<>();
	
	linkedList.add(22);
	linkedList.add(52);
	linkedList.add(29);
	linkedList.add(66);
	linkedList.add(33);
	
	System.out.println(linkedList);
	 
	linkedList.addFirst(100);		
	System.out.println("after add first: "+linkedList);
	
	linkedList.offerFirst(222);		
	System.out.println("after offer first: "+linkedList);

Output

[22, 52, 29, 66, 33]
after add first: [100, 22, 52, 29, 66, 33]
after add first: [222, 100, 22, 52, 29, 66, 33]

To add an element to the end of the list, methods offer, addLast or offerLast can be used.

	linkedList.addLast(333);
	linkedList.offerLast(444);
	linkedList.offer(555);
	System.out.println(linkedList);

Output

[222, 100, 22, 52, 29, 66, 33, 333, 444]

To retrieve first element, you can use getFirst, peek or peekFirst methods. To retrieve last element, you can use getLast or peekLast methods. The difference between peek methods and get methods is that get methods throw exception if list is empty, whereas peek methods return null.

	LinkedList<Integer> linkedList = new LinkedList<>();
	
	linkedList.add(22);
	linkedList.add(52);
	linkedList.add(29);
	linkedList.add(66);
	linkedList.add(33);		
	
	System.out.println(linkedList);
	System.out.println("first element: "+linkedList.getFirst());
	System.out.println("first element: "+linkedList.peek());
	System.out.println("first element: "+linkedList.peekFirst());
	
	System.out.println("last element: "+linkedList.getLast());
	System.out.println("last element: "+linkedList.peekLast());

Output

[22, 52, 29, 66, 33]
first element: 22
first element: 22
first element: 22
last element: 33
last element: 33

To retrieve and remove first element, you can use poll, pollFirst, remove or removeFirst methods. To retrieve and remove last element, you can use pollLast or removeLast methods. The difference between poll methods and remove methods is that remove methods throw exception if list is empty, whereas poll methods return null.

Vector

Vector is similar to array list but it provides synchronized operation so that only one thread is allowed to make changes to elements or add elements. It is better to use ArrayList if your program is thread-safe. You can create synchronized array list, using synchronizedList method of Collections class.

	List<Integer> lst = new ArrayList<>();
	lst = Collections.synchronizedList(lst);

Stack

Stack represents a last in first out (LIFO) stack of objects. Method push adds the given element at top of the stack. Method pop removes and returns element at the top of stack. Method peek returns the top object without removing it from stack. You can check to see if an element exists on stack or not by using search method and passing the element to it.

	Stack<Integer> stack = new Stack<>();
	stack.push(22);
	stack.push(33);
	stack.push(44);
	
	System.out.println(stack);		
	System.out.println("pop element: "+stack.pop());
	System.out.println("after pop: "+stack);

Output

[22, 33, 44]
pop element: 44
after pop: [22, 33]