Collections
Advanced Programming
SUT • Spring 2019
Contents
-
Containers
-
Collection
-
Set
-
Map
-
LinkedList
-
Iterator
Lists
Array
-
Suppose we have an array of students
-
Student[] students = new Student[34];
-
-
What if we do not know the array size?
-
A default initial size
-
-
What if we want to add more students to array?
-
Double the size of array
-
Copy old elements
-
-
What if we want to remove some students from array?
-
Nullify the element & shift the others
-
-
We need a dynamic array
Imagine if arrays was sth like:
Student[] students = new Student[0];
students.add(new Student("Ali Alavi"));
students.add(new Student("Taghi Taghavi"));
System.out.println(students[1]);
students.remove(0);
// But arrays are not so cute!
ArrayList
-
Java introduces Collection classes for this purpose
ArrayList students = new ArrayList();
students.add(new Student("Ali Alavi"));
students.add(new Student("Taghi Taghavi"));
students.remove(0);
Generic ArrayList
- ArrayList is also a generic type
ArrayList<Student> students = new ArrayList<Student>();
students.add(new Student("Ali Alavi"));
students.add(new Student("Taghi Taghavi"));
students.remove(0);
students.remove(new Student("Ali Alavi"));
Student student = students.get(0);
System.out.println(student);
// ArrayList<T> implements generic interface List<T>
Interface
interface List<E>{
int size();
boolean isEmpty();
boolean contains(Object o);
boolean add(E e);
boolean remove(Object o);
void clear();
E get(int index);
E set(int index, E element);
void add(int index, E element);
E remove(int index);
int indexOf(Object o);
int lastIndexOf(Object o);
List<E> subList(int fromIndex, int toIndex);
}
Usage
ArrayList<String> list = new ArrayList<String>();
Scanner scanner = new Scanner(System.in);
while(true){
String input = scanner.next();
if(input.equalsIgnoreCase("exit"))
break;
list.add(input);
}
if(list.isEmpty()){
System.out.println("No string entered");
}else{
System.out.println("" + list.size() +
" strings enetered");
if(list.contains("Ali"))
System.out.println("Ali Found!");
for (String s : list) {
System.out.println(s);
}
}
ArrayList or Array? That is the question
-
Do we need a dynamic array?
-
Add
-
Remove
-
-
Performance issue
-
ArrayList is implemented using an array
Array to List
-
Guess how?
String[] strings = {"ali", "taghi"};
ArrayList<String> list =
new ArrayList<String>();
for (String string : strings) {
list.add(string);
}
List to Array
-
Two methods:
-
Object[] toArray();
-
<T> T[] toArray(T[] a);
-
ArrayList<String> list = new ArrayList<String>();
Object[] array = list.toArray();
String[] array2 = list.toArray(new String[list.size()]);
Tell Me…
ArrayList<String> as;
ArrayList<Object> ao;
List<Object> lo;
List<String> ls;
-
True/False?
-
ArrayList<String> is subclass of List<String>
-
ls = as;
-
-
ArrayList<String> is subclass of ArrayList<Object>
-
ao = as;
-
-
ArrayList<String> is subclass of List<Object>
-
lo = as;
-
-
ArrayList Implementation
-
In the heart of an ArrayList, an array lives…
public class ArrayList<E> ... ,implements List<E>,...{
private Object[] elementData;
private int size;
public boolean add(E e) {
ensureCapacity(size + 1);
elementData[size++] = e;
return true;
}
}
Tell Me…
-
Why toArray() returns Object[]?
Collection
- Collection is super-class of many containers
public interface Collection<E> {
int size();
boolean isEmpty();
boolean contains(Object o);
boolean add(E e);
boolean remove(Object o);
void clear();
Object[] toArray();
<T> T[] toArray(T[] a);
}
LinkedList
-
LinkedList and ArrayList are both subclass of List
-
ArrayList is implemented by an array
-
LinkedList is implemented by a doubly linked list
-
It is used like an ArrayList
-
Because they are brothers! (subclass of List)
-
Linked List
Doubly Linked List
LinkedList Example
List<String> list = new LinkedList<String>();
list.add("Ali");
list.add("Taghi");
System.out.println(list.get(0));
list.remove("Taghi");
for (String string : list) {
System.out.println(string);
}
ArrayList vs. LinkedList
-
LinkedList stores two links for each element
-
if you want to do many insertions and removals in the middle of a list
-
a LinkedList is better
-
-
If not, an ArrayList is typically faster
Array, ArrayList and LinkedList
How to Test Performance?
long start = System.currentTimeMillis();
doSomthing();
long end = System.currentTimeMillis();
System.err.println(end - start);
Set
Set
- A set is a an unordered list of disjoint elements
{1,2,3,1,4,2} = {4,3,2,1}
set.add(1)
set.add(2)
set.add(3)
set.add(1)
set.remove(1)
Set == {3,2}
Set
-
A set is a list with no duplicate
-
Suppose we want to implement such a class
-
How?!
Set Implementation
class Set<E> extends ArrayList<E>{
public boolean add(E e) {
if(!contains(e))
return super.add(e);
return false;
}
public boolean add(int index, E e) {...}
}
Set and equals() Method
-
When set.add(value) is invoked
-
It checks whether there is any element equal to value
-
If any equal element found, add will return
-
We should implement appropriate equals() method
-
equals() is invoked implicitly
HashSet
-
Set is an interface
-
public interface Set<E> extends Collection<E>
-
HashSet is one of its (popular) implementations
-
Set and HashSet are generic classes
-
public class HashSet<E> implements Set<E>
HashSet Example
Set<String> set= new HashSet<String>();
set.add("Ali");
set.add("Taghi");
set.add("Ali");
for (String string : set) {
System.out.println(string);
}
HashSet Example
Set<Student> set= new HashSet<Student>();
set.add(new Student("Ali"));
set.add(new Student("Taghi"));
set.add(new Student("Ali"));
set.remove(new Student("Taghi"));
for (Student student : set) {
System.out.println(student);
}
Set or List?
-
List provides access via an index
-
Set does not
-
-
List is ordered
-
Set checks for duplicates
-
List is (usually) better in performance
-
Set may be better in memory consumption
-
-
Should we allow duplicates?
-
If not, use sets
-
-
HashSet is not implemented by a List
Map
Map
-
Map is not a collection
-
Map is a table
-
public interface Map<K,V>
-
Map<K, V> is something like a List<Pair<K,V>>
-
First element of each pair is called the key
-
Second element of each pair is called the value
-
Duplicate for keys is not allowed
-
Duplicate for values is possible
Example
Command | Keys | Values |
---|---|---|
map.put(87300876, “Ali Alavi”) | 87300876 | Ali Alavi |
map.put(87234431, “Taghi Taghavi”) | 87300876 | Ali Alavi |
87234431 | Taghi Taghavi | |
map.put(87300876, “Naghi Naghavi”) | 87300876 | Naghi Naghavi |
87234431 | Taghi Taghavi |
Interface
public interface Map<K,V> {
int size();
boolean isEmpty();
boolean containsKey(Object key);
boolean containsValue(Object value);
V get(Object key);
V put(K key, V value);
V remove(Object key);
void putAll(Map<? extends K, ? extends V> m);
void clear();
Set<K> keySet();
Collection<V> values();
Set<Map.Entry<K, V>> entrySet();
interface Entry<K,V> {
K getKey();
V getValue();
V setValue(V value);
}
}
HashMap
-
Map is an interface
-
public interface Map<K,V>
-
HashMap is one of its (popular) implementations
-
public class HashMap<K,V> implements Map<K,V>
HashMap Example
Map<Integer, String> map = new HashMap<>();
map.put(87300876, "Ali Alavi");
map.put(87234431, "Taghi Taghavi");
map.put(87300876, "Naghi Naghavi");
String name = map.get(87300876);
System.out.println(name);
HashMap Example
Map<Student, Double> map = new HashMap<>();
map.put(new Student("Ali Alavi"), new Double(18.76));
map.put(new Student("Taghi Taghavi"), new Double(15.43));
map.put(new Student("Naghi Naghavi"), new Double(17.26));
map.put(new Student("Naghi Naghavi"), new Double(15.26));
map.remove(new Student("Naghi Naghavi"));
Double average = map.get(new Student("Taghi Taghavi"));
System.out.println("Avg of Taghi=" + average);
for(Student student : map.keySet()){
System.out.println(student.toString());
}
Double totalSum = 0.0;
for(Double avg : map.values()){
totalSum += avg;
}
System.out.println("Total Average = " + (totalSum/map.size()));
Iterator
Iterator
-
Iterator is a mechanism for walking on elements of a collection
-
Before foreach (before Java5) it was the only mechanism
-
iterator() is declared in Iterable interface
-
In fact for-each is applicable on any Iterable object
Iterator
public interface Iterable<T> {
Iterator<T> iterator();
}
public interface Collection<E> extends Iterable<E> {…}
Iterator Class
ArrayList<Integer> arrayList = new ArrayList<Integer>();
arrayList.add(4);
arrayList.add(5);
for (Integer next : arrayList) {
System.out.println(next);
}
Iterator<Integer> iterator = arrayList.iterator();
while(iterator.hasNext()){
Integer next = iterator.next();
System.out.println(next);
}
Concurrent Modification
-
Suppose some processes are modifying the same collection
-
Java containers have a mechanism to prevent it
-
Suppose you’re in the middle of iterating through a container
-
And then some other process steps in and changes an object in that container
-
Insert, remove, …
-
-
there are many scenarios for disaster.
-
Maybe you’ve already passed that element in the container
-
Maybe it’s ahead of you
-
Maybe the size of the container shrinks after you call size( )
-
Fail Fast Aspect
-
If a collection is modified by one of its methods after an iterator is created for that collection
-
The iterator immediately becomes invalid
-
Any operations performed with the iterator after this point throw ConcurrentModificationExceptions
-
For this reason, iterators are said to be “fail fast”
ConcurrentModificationException
public class FailFast {
public static void main(String[] args) {
Collection<String> c = new ArrayList<String>();
Iterator<String> it = c.iterator();
c.add("An object");
String s = it.next(); // Exception line
}
}
ConcurrentModificationException
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
for (Integer integer: list) // Exception line
if(integer.equals(2))
list.remove(integer);
Arrays
- A utility class with many useful static methods
- For arrays
- With methods for
- Copy
- Fill
- Sort
- Search
- …
Arrays
Long[] array = new Long[100];
Arrays.fill(array, 5);
Long[] copy = Arrays.copyOf(array, 200);
//An unmodifiable list:
List<Integer> asList = Arrays.asList(1, 2 , 3, 4);
List<Long> asList2 = Arrays.asList(array);
Arrays.sort(array);
Collections
- A utility class for collections
- Copy
- Fill
- Sort
- Search
- …
Collections
TODO
-
Write the method
-
removeAlis(List<String> names)
-
It takes a List<String> as parameter
-
Removes all the elements which start with “Ali”
Bad Implementation
static void removeAli(List<String> list){
for (String string : list)
if(string.startsWith("Ali"))
list.remove(string);
}
Good Implementation
public static void removeAli(ArrayList<String> list){
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()) {
String string = iterator.next();
if(string.startsWith("Ali"))
iterator.remove();
}
}
Good Implementation
public static void removeAli(ArrayList<String> list){
for (Iterator<String> iterator = list.iterator();
iterator.hasNext(); ) {
String string = iterator.next();
if(string.startsWith("Ali"))
iterator.remove();
}
}
Another Correct Implementation
public static void removeAli(ArrayList<String> list){
for (int i = list.size()-1; i >= 0; i--)
if(list.get(i).startsWith("Ali"))
list.remove(i);
}
hashCode()
-
hashCode() is one of Object methods
-
like equals, toString and finalize
-
-
It creates a hash from the object
-
Used in classes like HashMap and HashSet for faster retrieval
Title Text
Collections
By Behnam Hatami
Collections
Collections / Advanced Programming Course @ SUT, Spring 2019
- 1,159