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

COLLECTIONS & GENERICS

TOPICS

◼ Iterator
◼ Collection Framework
◼ Collections
◼ Lists
◼ Maps
◼ Generics
◼ Lists Implementation
COLLECTIONS
COLLECTIONS INTRODUCTION

• Collections are container abstractions that allow you to aggregate a group (collection) of objects

• The collections framework allows different kinds of collections to be dealt with in an

implementation-independent manner

• Insulate client programs from the implementation.

• Can grow dynamically

• Contain only Objects (reference types)

• Heterogeneous (stores different data types)

• Can be thread safe (concurrent access)

• Can be not-modifiable
HOW COLLECTIONS ARE USED

• Collections are typically used to process a group of objects in a similar manner

• send emails to (a collection of) all our customers


• send emails to (a collection of) delinquent customers
• process (a collection of) purchases for a given customer
• ship (a collection of) inventory items to a distributor
• compare the symptoms (of a collection) of patients
• compare (a collection of) radiological images of a patient
• generate alarms for (a collection of) telemetry values
• But they are also used to pass a group of objects between layers in an application
THE COLLECTIONS FRAMEWORK

Iterable

Collection Map

Set List Queue


SortedMap

SortedSet
INTERFACE ITERABLE

◼ Iterable only has one method


◼ public Iterator<T> iterator();
◼ Returns an iterator

◼ What’s an iterator?
◼ It provides methods for visiting (forward direction only) and removing elements of a collections:
◼ boolean hasNext();
◼ T next();
◼ void remove();
COLLECTION ABSTRACTIONS

• Various collection abstractions exist


– array (ordered collection with access via index operations)
– list (ordered collection with access via iterators)
– queue (first in, first out via enqueue/dequeue operations)
– stack (last in, first out via push/pop operations)
– set (collection where all entries are guaranteed to be unique)
– map (keyword / value pairs)
COLLECTIONS FRAMEWORK
• Based on interfaces and implementing classes
• Interfaces • Implementing Classes
– Collection – n/a
– Set – HashSet, TreeSet
– List – ArrayList, LinkedList, Vector
– Map – HashMap, TreeMap
Note: the separation of an interface from its
implementation facilitated the creation of multiple
implementations for a given collection interface
COLLECTION FRAMEWORK COMPONENTS

The Java collections framework consists of:


◼ Collection interfaces representing different types of collections (sets, lists, etc)
◼ General purpose implementations (like ArrayList or HashSet)
◼ Abstract implementations to support custom implementations
◼ Algorithms defined in static utility methods that operate on collections (like Collections.sort(List list))
◼ Infrastructure interfaces that support collections (like Iterator)
THE COLLECTION INTERFACE

Collection is the root interface of the collections framework, declaring basic operations such as:
◼ add(E e) to add elements to the collection
◼ contains(Object key) to determine whether the collection contains key
◼ isEmpty() to test the collection for emptiness
◼ iterator() to get an interator over the elements of the collection
◼ remove(Object o) to remove a single instance of o from the collection, if present
◼ size() to find out the number of elements in the collection
None of the collection implementations in the Java library implement Collection directly. Instead they implement List
or Set.
THE COLLECTION INTERFACE - OPERATIONS
public interface Collection
{
// Basic Operations
int size();
boolean isEmpty();
boolean contains(Object element);
boolean add(Object element); // Optional
boolean remove(Object element); // Optional
Iterator iterator();
// Bulk Operations
boolean containsAll(Collection c);
boolean addAll(Collection c); // Optional
boolean removeAll(Collection c); // Optional
boolean retainAll(Collection c); // Optional
void clear(); // Optional
// Array Operations
Object[] toArray();
Object[] toArray(Object a[]);
}
LISTS

The List interface extends the Collection interface to represent ordered collections, or sequences. List has
◼ methods for positional (indexed) access to elements
◼ add(int, Object)
◼ get(int index)
◼ indexOf(Object o)
◼ remove(int index)
◼ set(int index, E element)) //replace method
◼ Methods for searching
◼ indexOf(Object)
◼ lastIndexOf(Object)
◼ a special iterator, ListIterator
◼ that allows element insertion and replacement, and bidirectional access in addition to the normal operations that the Iterator
interface provides; and methods to obtain a ListIterator
◼ Extraction for sublist
◼ subList(int fromIndex, int toIndex) that returns a view of a portion of the list.
LIST

◼ Further requirements compared to the Collection Interface


◼ add(Object)
◼ adds at the end of the list
◼ remove(Object)
◼ removes at the start of the list
◼ list1.equals(list2)
◼ the ordering of the elements is taken into consideration
◼ Extra requirements to the method hashCode.
◼ list1.equals(list2) implies that list1.hashCode()==list2.hashCode()
ARRAYLIST AND LINKEDLIST

◼ ArralyList and LinkedList are the two basic List implementations provided in the Java standard library.
◼ Both implement the List interface.
◼ ArrayList
◼ Array based implementation
◼ Elements can be accessed directly via the get and set methods
◼ Default choice for simple sequence
◼ LinkedList
◼ Based on a double linked list
◼ Gives better performance on add and remove compared to ArrayList
◼ Gives poorer performance on get and set methods compared to ArrayList
ARRAYLIST

Create an ArrayList with operator new:


◼ ArrayList tasks = new ArrayList();
Add items with add():
◼ tasks.add("Eat");
◼ tasks.add("Sleep");
◼ tasks.add(7);
Traverse with for-each loop:
for (Object task: tasks)
{
System.out.println(task);
}
//Note that the for-each loop implicitly uses an iterator.
ARRAYLIST IMPLEMENTATION

List<Customer> delinquentCustomers = new ArrayList<Customer>();


ResultSet rs = getDelinquentCustomers(); //returns a JDBC ResultSet from database
while (rs.next())
{
Customer customer = new Customer();
customer.setId(rs.getInt(“id”));
customer.setName(rs.getString(“name”));

delinquentCustomers.add(customer); // add customer to the collection
}
Note: for brevity, try/catch exception handling is not shown
WHAT’S LACKING WITH COLLECTIONS?

• All of the collection interfaces/classes operated on the class “Object”, thus

– the method signatures were coupled to “Object”; e.g.,


• Collection.add (Object o)
• Object Collection.remove()
– their usage required casting
• Entities placed in the collections are “up cast” to “Object”
• Entities retrieved from the collections require a downcast

– they have to be “down cast” to the expected class


» Customer customer = (Customer) myList.get(0)
– so the collections were not “type safe”
WHAT’S LACKING WITH COLLECTIONS

• Because the collections used Object:


– a given collection instantiation could be populated with any kind of object (actually, multiple kinds)
• because all objects are “up cast” to class Object
– So there was no guarantee what types of objects were in a given collection
• this could produce a runtime exception at the point of removal

◼ – e.g., ClassCastException
◼ » Note: there are ways to get around this, but the code is clumsy
• There had to be a better way: enter generics
SUMMARY

◼ Array
◼ Holds objects of known type.
◼ Fixed size.
◼ Collections
◼ Generalization of the array concept.
◼ Set of interfaces defined in Java for storing object.
◼ Multiple types of objects.
◼ Resizable.
◼ Major changes to in Java 5
◼ Introduced generics
MAP INTERFACE

• The Map interface allows you to store/retrieve objects by keys (lookup names)
– so the map consists of keyword / value pairs
• the keyword is the lookup name
• the value is the object placed/retrieved in/from the map

– Note: each key maps to exactly one value in the collection


• there is a one-to-one relationship

• You declare/parameterize a Map with the types of objects you intend to use with the map

– both the keyword and value are parameterized


• The Map’s keys (lookup names) are not guaranteed to be sorted in any particular order

– the order will vary based on the implementing class you use. if you swap impls, the order could be different
• So, if the sorting of keys is important in your application, use the SortedMap interface

– and its implementing class TreeMap…


MAP OPERATIONS

◼ Core Operations
– boolean clear();
– boolean containsKey(K key);
– boolean containsValue(V value);
– V get(K key) Where K and V are generic types that are parameterized with
– boolean isEmpty(); actual types at the point of instantiation
– Set<key> keySet();
– V put (K key, V value);
– V remove (Object key)
– int size();
MAP INTERFACE

• Map definition provided by Java:


– public interface Map<K,V> {…}
• where K is the generic type for the Keyword
• and V is the generic type for the Value
• So to declare a Map in your application, …
• with String keywords and Customer values:
Map<String, Customer> customers = new HashMap<String, Customer>();
• with Integer keywords and Account values:
Map<Integer, Account> accounts = new HashMap<Integer, Accounts>();
MAPS INTERFACE

• The map’s key must be unique for each value placed in the map

– So, for a Customer object, consider the following possible keys:


• name
• ssn (social security #)
• id (e.g, database id)
– Since “name” is not guaranteed to be unique, it’s not a good choice for the key
• but ssn and database id are unique identifiers

◼ – so they could be used as the key for a Customer map


MAP IMPLEMENTATION

• Suppose we wanted to create a customer map using ssn as the keyword; then to

create and use a customer map we have:

public class Customer


Map<Integer, Customer> customers = new HashMap<Integer,Customer>();
{ Customer customer = new Customer();
private string name; …
private int ssn; …

private int id; // place a customer in the map using their ssn
… customers.put(customer.getSSN(), customer);
}
// retrieve a customer from the map using an ssn
Customer customer = customers.get(123456789);
MAP IMPLEMENTATION

◼ To iterate through all the keys /values:

Map<Integer, Customer> customers = new HashMap<Integer, Customer>();



Iterator<Integer> ids= customers.keySet().iterator();
while(ids.hasNext())
{
Integer id = ids.next();
System.out.println(“id: " + id+ ", value: " + customers.get(id));
}
QUEUES

• Suppose we have a need to process incoming messages on a “first come


basis”
– We would place them in a FIFO queue
• where FIFO is implemented by a LinkedList
private Queue<Message> msgQueue = new LinkedList<Message>();

public void addMessageToQueue(Message msg) throws Exception

{
msgQueue.add(msg);
}
GENERICS
GENERICS

◼ Supply a type argument in the angle brackets. Read ArrayList<string> as “ArrayList of String”
ArrayList<string> strings = new ArrayList<string>();
strings.add("Helluva");
strings.add("Engineer!");
◼ If we try to add an object that isn’t a String, we get a compile error:
Integer BULL_DOG = Integer.MIN_VALUE;
strings.add(BULL_DOG); // Won’t compile
◼ With a typed collection, we get autoboxing on insertion and retrieval:
ArrayList ints = new ArrayList<>();
ints.add(42);
int num = ints.get(0);
◼ Notice that we didn’t need to supply the type parameter in the creation expression above. Java inferred the type parameter from the declaration.
(Note: this only works in Java 7 and above.)
ARRAYS
ARRAYS

class Car{}; // minimal dummy class


class Car[] cars1; // null reference
Car[] cars2 = new Car[10]; // null references
for (int i = 0; i < cars2.length; i++)
cars2[i] = new Car();
// aggregated initialization
Car[] cars3 = {new Car(), new Car(), new Car(), new Car()};
cars1 = cars3;
ARRAYS

◼ Most efficient way to hold references to objects.

Data Car Car Car


Index 0 1 2 3 4 5

◼ Advantages
◼ Knows the type it holds, i.e., compile-time type checking
◼ Knows its size, i.e., ask for the length
◼ Can hold primitive types directly
◼ Automatic boundary checking, raises exceptions if violated
◼ Disadvantages
◼ Only hold one type of objects (including primitives)
◼ Fixed size

You might also like