Lecture 16 - Java Collections API

Download as pdf or txt
Download as pdf or txt
You are on page 1of 68

Lecture # 16: Java Collections API

SE 241 Advance Computer Programming


Muhammad Imran adopted from Dr. Usman Nasir
What is a Collection?
 An object that contains other objects or
groups multiple elements into a single unit.
 Used to store, retrieve and manipulate data.
 It can consist of any types of objects
Java Collection API
 Java Collections API provide a set of
classes and interfaces that makes it
easier to work with collections of objects
 Provides a basic set of Object Containers.
 Core data structures for everyday coding.
 Unified architecture for representing and
manipulating collections.
 It has Interfaces and Implementations
 There are two groups of standard
interfaces in Java Collections API:
 Collections
 Map

Collection Map
(interface) (interface)

List Set HashMap

** Partial map of API


classes
Generics in Collections
 A non-generic collection can store any type
of object (Any type)
 This helps in mixing object in collection but
then it is up to programmer to check and
type-cast it every time.
 Generics force the java programmer to
store a specific type of objects in a
collection.
 This way is efficient and reduces errors
 diamond operator <>are used to define
generics
Collections to Array
 Collection object can be used with Object
Arrays

Collection c = new ArrayList();


c.add(19);
c.add("hello");
Object[] array = c.toArray();
Collection Interface

java.util.Collection
Collection Interface
 Java Collection interface
(java.util.Collection) is one of the root
interfaces of the Java Collection API.
 You can not instantiate a Collection
directly, but its sub types are implemented
Collection collection = new ArrayList();

 Available collection types that extends the


Java Collection interface:
 List, Set, SortedSet, NavigableSet, Queue,
Deque
Some methods of Collection
Interface
 boolean add(Object o)
 Ensures that this collection contains the specified
element.
 void clear()
 Removes all of the elements from this collection
 boolean contains(Object o)
 Returns true if this collection contains the specified
element.
 boolean equals(Object o)
 Compares the specified object with this collection for
equality.
 boolean isEmpty()
 Returns true if this collection contains no elements.
 Iterator iterator()
 Returns an iterator over the elements in this
collection.
 boolean remove(Object o)
 Removes a single instance of the specified element
from this collection, if it is present
 int size()
 Returns the number of elements in this collection.
 Object[] toArray()
 Returns an array containing all of the elements in this
collection
Java List
 java.util.List is an interface that represents
an ordered sequence of objects.
 Each element in a Java List has an index
starting from 0.
 Any Java object can be added to a List.
 Available implementations of List
 java.util.ArrayList
 java.util.LinkedList
 java.util.Vector //deprecated
 java.util.Stack
ArrayList
 ArrayList implements List interface
 The ArrayList will automatically increase to
accommodate elements.
 ArrayList operations are slightly slower
than array operations.
 Use
import java.util.ArrayList;
 Declaration
List myList = new ArrayList();
// Adding elements
myList.add("Malik");
myList.add(30);
myList.add(11.25);

//Compile Error:incompatible types: java.lang.Object


//cannot be converted
String name = myList.get(0);
int age= myList.get(1);
double score= myList.get(2);
 Declaration
List myList = new ArrayList();
// Adding elements
myList.add("Malik");
myList.add(30);
myList.add(11.25);

//Explicit casting is required for each element


String name = (String) myList.get(0);
int age= (int) myList.get(1);
double score= (double) myList.get(2);
 After using generics we do not need to type
cast as entire collection type casted to given
type.

List<String> listGen = new ArrayList<String>();


listGen.add("hello");
String ss = listGen.get(0);
listGen.add(50);//this will give error now
Why??
 Another style of declaration:
List<String> listGen = new ArrayList<>();
import java.util.* ;
public class ArrayListExample{
public static void main ( String[ ] args) {
// Create an ArrayList that holds references to String
List<String> names = new ArrayList<String>();
// Add three String references
names.add("Malik"); names.add("Bashir");
names.add("Zameer");
// Access and print out the three String Objects
System.out.println(“Element 0: " + names.get(0) );
System.out.println(”Element 1: " + names.get(1) );
System.out.println(”Element 2: " + names.get(2) );
Element 0: Malik
}
Element 1: Bashir
} Element 2: Zameer
public class Customer{
public Customer(int aId, String aName){ customerId=aId;
customerName=aName; }
public String toString() { return "Customer: id: "+customerId+"
"+customerName; }
private int customerId; private String customerName;}
_____________________________________________________
______
import java.util.*;
public class Example2{
public static void main ( String[ ] args) {
ArrayList <Customer> listCustomer = new
ArrayList<Customer>(); Example2
listCustomer.add(new Customer(1,"Ali")); Customer: id: 2
Customer cust2=new Customer(2,"Sameer"); Sameer
listCustomer.add(1,cust2);
Linked List
 LinkedList is implemented as a double linked
list.
 List<String> list = new LinkedList<>();
list.add("hello");
list.add("hi");
list.add("bye");

System.out.println("Element 0: " + list.get(0) );


System.out.println("Element 1: " + list.get(1) );
System.out.println("Element 2: " + list.get(2) );
ArrayList versus LinkedList
 ArrayList  LinkedList
 An array that  Classic doubly
linked list.
resizes when it
 Constant time for
gets full. insertion and
 Insertion to the removal anywhere
front or middle is in the list.
expensive.  Slower iteration.
 get(int) very slow
 Provides fast
(implemented by
iterator and get(int) iterating).
methods.
Set Interface
 Set interface extends Collection interface.
 In a set, no duplicates are allowed.
 Every element in a set must be unique. You
can simply add elements to a set, and
duplicates will be removed automatically.

 Some of the implementing classes are:


 java.util.HashSet
 java.util.EnumSet
 java.util.LinkedHashSet
 java.util.TreeSet
HashSet class
 Creates a collections and uses a hash
table for storage
 Uses hashing
 Execution time of basic operations is
constant
 No order maintained
Example: HashSet
import java.util.*;
public class FindDups {
public static void main(String args[]) {
Set<String> myset = new HashSet<String>();
for (int i=0; i < args.length; i++) {
if (! myset.add(args[i]) )
System.out.println("Duplicate detected: "
+args[i]);}
System.out.println(myset.size() + " distinct
words detected: " + myset); } }
Running the Example
$ java FindDups i came i saw i left
Duplicate word detected: i
Duplicate word detected: i
4 distinct words detected: [came, i, left, saw]
Set vs List
 Set  List
 Faithful to the  Sequential
mathematical structures.
definition.  Duplicates
 No methods added allowed.
to Collection  Implements get
(simply enforces and remove
“no duplicates” methods using
rule using the integer index.
equals method).
Queue
 java.util.Queue interface represents queue
data structure.
 It is designed to have elements inserted at the
end of the queue and removed from the top.
 Queue interface is a subtype of the Java
Collection interface

 Java Queue Implementations


 java.util.LinkedList
 java.util.PriorityQueue
//import java.util.Queue;
// Queue using a LinkedList
Queue<String> waitingQueue = new LinkedList<>();
// Adding elements to the Queue
waitingQueue.add("Abdul");
waitingQueue.add("Bashir");
waitingQueue.add("Karim");
System.out.println("WaitingQueue : " + waitingQueue);
// Removing an element (Dequeue operation)
String name = waitingQueue.remove();
System.out.println("Removed from queue : " + name);
System.out.println("New queue: " + waitingQueue);

Output:
WaitingQueue : [Abdul, Bashir,
Karim]
Removed from queue : Abdul
Map Interface

java.util.Map
Map Interface
 java.util.Map represents a mapping
between a key and a value.
 Maps stores associations between keys
and values
 Key/values both are objects and keys are
unique
 Not collections, but provide a collections
view
 Java Collections API contains the following
Map implementations:
 java.util.HashMap
 java.util.Hashtable
 java.util.EnumMap
 java.util.IdentityHashMap
 java.util.LinkedHashMap
 java.util.Properties (must study on your own)
 java.util.TreeMap
 java.util.WeakHashMap
Map Interface - Methods
 Object put(Object key, Object value)
 Associates the specified value with the
specified key in this map
 //adds
 Object get(Object key)
 Returns the value to which this map maps the
specified key.
 //get
 boolean isEmpty()
 Returns true if this map contains no key-value
mappings.
HashMap Example
public static void main(String[] args) {
HashMap<Integer, String> map = new
HashMap<Integer, String>();
map.put(10, "Ali"); map.put(12, "Jamal");
map.put(12, "Asad"); //What happens to
duplicate keys
map.put(14, "Samad");
System.out.println("Size of map is:- " +
map.size());
System.out.println(map);
System.out.println("The value for key is :" +
map.get(10));
Output:
Size of map is: 3
{10=Ali, 12=Asad, 14=Samad}
The value for key is : Ali
{}
Hashtable (depreciated now)
Hashtable<String, MyStudent> hashTbl = new
Hashtable<>();
hashTbl.put ("1", new MyStudent("1","Ali");
hashTbl.put ("2", new
MyStudent("2","Saleem"));
hashTbl.put ("3", new MyStudent("z","Zafar"));
//hashTbl.put (null, new
MyStudent("z","Zafar"));
//hashTbl.put("4", null);
System.out.println (hashTbl);
{3=z,Zafar, 2=2,Saleem, 1=1,Ali}
HashMap vs HashTable
Hashtable<Integer,String> ht=new
Hashtable<>();
ht.put(101,"Samad"); ht.put(101,"Ali");
ht.put(102,"Khalid"); ht.put(103,"Ali");
System.out.println("--------Hash table---------");
System.out.println(ht);
HashMap<Integer,String> hm=new
HashMap<>();
hm.put(101,"Samad"); hm.put(101,"Ali");
hm.put(null,null); hm.put(103,"Ali");
System.out.println("-------Hash map----------");
System.out.println(hm);
Output
-------------Hash table--------------
{103=Ali, 102=Khalid, 101=Ali}
-----------Hash map-----------
{null=null, 101=Ali, 103=Ali}
Hashmap vs Hashtable
 HashMap is non synchronized thus not-
thread safe
 HashMap allows one null key and multiple
null values whereas Hashtable doesn’t
allow any null key or value.
 HashMap is generally preferred over
HashTable if thread synchronization is not
needed
equals() and hashCode()
Java hashCode() and equals()
 In Collection both hashCode() and equals()
methods are used to compare objects in
collections.

 equals( ) is used in most collections to


determine if a collection contains a given
element.
List list = new ArrayList();
list.add("123");
boolean contains123 = list.contains("123");
//contains will be calling equals of each element with
"123" and compare string
 Shallow comparison:
 The default implementation of equals method is
defined in Java.lang.Object class which simply
checks if two Object references refer to the same
Object.
 Deep Comparison:
 That means data members of Objects are to be
compared with one another.

 For user defined Object equals() must be


overloaded, as it depends on your application
that when two objects are equal.
public class Employee {
private long employeeId;
private String name;
public Employee(long employeeId, String aName) {
this.employeeId = employeeId;
this.name = aName;
}

public static void main(String[] args) {


Employee one = new Employee(0100, "Ali");
Employee two = new Employee(0100, "Ali");
System.out.println(one.equals(two));
} Output: false
}//
public class Employee {
//overriding equals Employee equals if id is same
@Override
public boolean equals(Object o) {
if (o == null) return false;
if (!(o instanceof Employee)) return false;

Employee other = (Employee) o;


return this.employeeId == other.employeeId;
}
public static void main(String[] args) {
Employee one = new Employee(0100, "Ali");
Employee two = new Employee(0100, "Ali");
System.out.println( one.equals(two) );
} Output: true
}//
 Overriding of equals depends on
implementation:
 It can be comparing id only if you have to
lookup an Employee object from a cache.
 It can be comparing every field if you have to
check that if a copy of an Employee object has
changed from the original.
hashCode( )
 This method is provided by java.lang.Object and
returns an integer representation of the object
memory address.
 Used when inserting/comparing/removing objects
into HashTable, HashMap or HashSet.
 By default, this method returns a random integer
that is unique for each instance
 You should override if you need it but best is
to follow this
 If object1 and object2 are equal according to their
equals() method, they must also have the same
hash code.
 If object1 and object2 have the same hash code,
they do not have to be equal too.
public class Employee {
private long employeeId; private String name;
@Override
public int hashCode(){
return (int) employeeId;
}

public static void main(String[] args) {


Employee one = new Employee(0100, "Ali");
Employee two = new Employee(0100, "Ali");
System.out.println(one.equals(two));
}
Output: true
}//
Some guidelines
 As a rule, when you override equals() you
must also override hashcode()

 You should only execute an equals() method


for objects that have the same hashcode.
 You should not execute equals() when the
hashcode is different.
 When a hashcode() comparison returns false,
the equals() method must also return false and
vice versa.
Iterator and Iterable
Iterator
 Iterator interface gives a standardized way
for iterating elements within a collection.
 All collections implements the iterator
 Allows elements of any collection to be
accessed through iterators
 Replaces
int counter;
int size = collection.size();
for (counter=0; counter < size; counter++){
Object value = collection.get(counter);
}

With

Iterator i = collection.iterator();
while(i.hasNext()) {
Object value = i.next();
}
Using Iterator
ArrayList<String> names = new ArrayList<>();
names.add("Sameer");
names.add("Waleed");
names.add("Sami");

Iterator it = names.iterator();

while ( it.hasNext() ){
String obj = (String)it.next();
System.out.println(obj);
}
 Some collections do not allow modification
of the collection while using Iterator.
 Throws ConcurrentModificationException on
add( ) but not on remove( )
Iterable
 A class that implements the Java Iterable
(java.lang.Iterable) interface can be
iterated with the Java for-each loop.
 Several classes in Java that implements
the Java Iterable interface.
 The Collection interface extends Iterable,
so all subtypes of Collection also
implement the Iterable interface.
 Java List and Set interfaces etc.
//ArrayList is Iterable
List list = new ArrayList();
list.add("one");
list.add("two");
list.add("three");
for(Object o : list){
System.out.println(o.toString());
}
Java.util.Iterable Interface has only method
public Iterator <T> iterator( )

public interface Iterable<T> {


public Iterator<T> iterator();
}

 To make your own classes Iterable


requires implementing Iterable interface.
public class Persons implements Iterable {
private List<Person> persons = new
ArrayList<Person>();

public Iterator<Person> iterator() {


return this.persons.iterator( );
}
}

Persons persons = new Persons();//assuming some


elements are in List
for(Person person : persons) {
// do something with person object.
}
Comparator and Comparable
Comparable
 Comparable is an interface that helps in defining a
strategy of comparing an object with other objects
of the same type.
 Class's “natural ordering”.

 Collections.sort( ) use object that have


implemented Comparable interface.

public interface Comparable {


/* a negative integer, zero, or a positive integer as this object
is less than, equal to, or greater than the specified object.*/
public int compareTo(Object o);
}
Example
Lets take a class Player. Players are
compared with each other based on their
ranking
public class Player {
private int ranking;
private String name;
private int age;

// constructor, getters, setters


}
List<Player> hockeyteam = new ArrayList<>();
hockeyteam.add(new Player(12, "Zaeem",32));
hockeyteam.add(new Player(18, "Samad",29));
hockeyteam.add(new Player(07, "Abdul",21));

System.out.println("Before Team : " +


hockeyteam);
Collections.sort(hockeyteam);//will not work
System.out.println("After Team : " +
hockeyteam);

//How does Java know how to compare Player A with


B?
public class Player implements
Comparable<Player>
{
//other methods and code remain
@Override
public int compareTo(Player otherPlayer) {
return (this.getRanking() -
otherPlayer.getRanking());
}
}
List<Player> hockeyteam = new ArrayList<>();
hockeyteam.add(new Player(12, "Zaeem",32));
hockeyteam.add(new Player(18, "Samad",29));
hockeyteam.add(new Player(07, "Abdul",21));

System.out.println("Before Team : " +


hockeyteam);
Collections.sort(hockeyteam);//will now
work
System.out.println("After Team : " +
Output:
hockeyteam);
Before Team : [Player{12, 'Zaeem', 32}, Player{7, 'Abdul', 21}, Player{18,
'Samad', 29}]
After Team : [Player{7, 'Abdul', 21}, Player{12, 'Zaeem', 32}, Player{18,
'Samad', 29}]
Comparator
 At time programmer needs to have multiple
logics to do comparisons of objects. This
become an issue as in compareTo method
you can have one logic.
 Using a class that implements the
Comparator interface can become as basis of
comparison logic.

 The user defined class does not need to


implement Comparable interface now with
this approach but that can be left as default
approach.
 Use javadoc to share info about comparison logic
Comparator Interface
 Comparator interface defines a compare
method with two arguments which
compares objects.
 Only only method:
public int compare(Obj one, Object two)
/*a negative integer, zero, or a positive integer as
the
* first argument is less than, equal to, or greater
than * the second.*/
import java.util.Comparator;
public class PlayerNameComparator implements
Comparator<Player> {
@Override
public int compare(Player firstPlayer, Player
secondPlayer) {
return
firstPlayer.getName().compareTo(secondPlayer.getN
ame());
}
}
//Age is used to compare
public class PlayerAgeComparator implements
Comparator<Player> {
@Override
public int compare(Player firstPlayer, Player
secondPlayer) {
return (firstPlayer.getAge() -
secondPlayer.getAge());
}
}
List<Player> hockeyteam = new ArrayList<>();

hockeyteam.add(new Player(12, "Zaeem", 32));


hockeyteam.add(new Player(18, "Samad", 29));
hockeyteam.add(new Player(07, "Basit", 33));
hockeyteam.add(new Player(10, "Hameed",
24));

System.out.println("Before Team: " +


hockeyteam + "\n---------------------");
Collections.sort(hockeyteam);
System.out.println("After Team :" +
hockeyteam);
PlayerAgeComparator compareAge = new
PlayerAgeComparator();
PlayerNameComparator compareName=new
PlayerNameComparator();
Collections.sort(hockeyteam, compareAge);
System.out.println("After Team (age): " +
hockeyteam);
Collections.sort(hockeyteam, compareName);
System.out.println("After Team (name): " +
hockeyteam);
Output:

Before Team: [Player{ rank:12, 'Zaeem', age: 32}, Player{ rank:18, 'Samad',
age: 29}, Player{ rank:7, 'Basit', age: 33}, Player{ rank:10, 'Hameed', age:
24}]
---------------------
After Team :[Player{ rank:7, 'Basit', age: 33}, Player{ rank:10, 'Hameed', age:
24}, Player{ rank:12, 'Zaeem', age: 32}, Player{ rank:18, 'Samad', age: 29}]

After Team (age): [Player{ rank:10, 'Hameed', age: 24}, Player{ rank:18,
'Samad', age: 29}, Player{ rank:12, 'Zaeem', age: 32}, Player{ rank:7, 'Basit',
age: 33}]

After Team (name): [Player{ rank:7, 'Basit', age: 33}, Player{ rank:10,
'Hameed', age: 24}, Player{ rank:18, 'Samad', age: 29}, Player{ rank:12,
'Zaeem', age: 32}]
§
Thank you
 Learn on your own
 java.util.PriorityQueue
 Java Properties

 Try to re-write the Employee class's hashCode


and equals methods following the given
guidelines of overloading these methods.

 How to write your own list of objects that


implements Iterable interface.

You might also like