• Java Collections API • Introduction to generics in Java • Lists • Stacks and queues • Sets • Maps • Summary - P3 Java API Collection

  • Java Collections API
  • Introduction to generics in Java • Lists • Stacks and queues
  • Sets • Maps • Summary

  Java Collections API

  Outline

  The Java Collections API

  Outline Data structures in Java Collections

  • The Java Collections API provides an implementation of all the data structures we have seen so far.
  • It is not necessarily the best implementation available, but its ready-made.
  • We will familiarize ourselves with how to use it: users of data structures only need to see the available operations, not the implementation encapsulation, information-hiding, separation of interface and implementation.
  • The Java Collections API provides the following data structures:
The Collection interface The Collection interface (2)

  • • (Almost) all data structure implementations in the • Additionally, the Collection interface specifies

  Collection Collections API implement the the following methods, all of which take another interface.

  Collection as their argument:

  • It defines, among others, the following methods:

  Iterators The need for generic programming

  • All Java collections have an iterator() method,

  What’s wrong with this code? which returns an Iterator object that steps through

  void addStuffToCollection(Collection c) { all its elements. c.add(new String("Hello world!"));

  • The Iterator object itself provides the following

  c.add(new String("Good bye!")); c.add(new Integer(95));

  methods:

  printCollection(c); } void printCollection(Collection c) {

  Iterator i = c.iterator(); while(i.hasNext()) {

  String item = (String) i.next(); System.out.println("Item: "+item);

  • Repeated calls of next() (until hasNext() returns

  } } ) will step through all elements.

  false • remove() can only be called once per call to next().

The need for generic programming, pt.2

  • Before Java 5.0, there was no way of keeping track of what types of elements a collection contains.
  • Thus, we had to cast variables all over the place. This is both:
    • – Cumbersome: casting when we shouldn’t have to, and – Error-prone: can cause run-time exceptions.

  • Generics are a way of restricting the type of elements a collection can contain.
  • Collections are now generic classes that take type parameters.
  • We can define our own generic types, classes, and methods.

  What’s wrong with this code? • The List interface represents the list data structure.

  ListTester program What is the output of java ListTester this is a test for lists?

  } }

  { List<String> myList = new ArrayList<String>(); for(int ii=0; ii<args.length; ii++) myList.add(0,args[ii]); while(!myList.isEmpty()) { String myString = myList.remove(0); System.out.println(myString); }

  import java.util.ArrayList; import java.util.List; public class ListTester { public static void main(String[] args)

  List

  } }

  String item = i.next(); System.out.println("Item: "+item);

  Iterator i = c.iterator(); while(i.hasNext()) {

  } void printCollection(Collection<String> c) {

  void addStuffToCollection(Collection<String> c) { c.add(new String("Hello world!")); c.add(new String("Good bye!")); c.add(new Integer(95)); printCollection(c);

  Instantiating generic classes with type parameters

  List<MyType> myList = new ArrayList<MyType>();

  Restricting collection element types

Example usage of List

  • Behaviour of standard Collection methods:
  • Adds methods for positional/indexed access: • Like Java arrays, the first element starts from 0.
  • There are two implementing classes: ArrayList and LinkedList.
  • Remember, you can’t instantiate an interface!
Implementation 1: ArrayList

  Implementation 2: LinkedList

  • LinkedList stores items non-contiguously as nodes that contain reference to the next node in the list.
  • Maintains a reference to the beginning of the list (initially set to null ).
  • As items are added, it allocates memory non- contiguously.
  • Inserting/deleting items in the middle does not require any shifting, just updating of next references O(1)
  • Accessing items in the middle (by index) requires counting from the beginning of the list O(n)
  • An ArrayList internally stores items as an array:
  • When instantiated, it allocates a contiguous block of memory. When full, it increases capacity by allocating a new, larger block (double the size?)
  • When inserting/deleting items in the middle, items must be shifted to the right/left O(N)
  • Accessing items in the middle (by index) is very fast as we know exactly where it is in memory O(1)

  Accessing items by index is not efficient with LinkedLists, whereas inserting/removing items in the middle is not efficient with ArrayLists.

  Tradeoff between ArrayList and LinkedList • The Stack class represents the stack data structure.

  Stack

Example usage of Stack

  • Behaviour of standard Collection methods:
  • Provides, among others, the following methods:
  • In practice, the Stack class is implemented as a subclass of Vector, an old data structure that is a kind of list.
  • All the above operations are O(1).

  import java.util.Stack; public class StackTester { public static void main(String[] args)

  { Stack<String> myStack = new Stack<String>(); for(int ii=0; ii<args.length; ii++) myStack.push(args[ii]); while(!myStack.isEmpty()) { String myString = myStack.pop(); System.out.println(myString); }

  } }

  StackTester program What is the output of Queues Example usage of Queue • The Queue interface represents the queue data structure.

  QueueTester program

  • Behaviour of standard Collection methods:

  import java.util.LinkedList; import java.util.Queue; public class QueueTester

  • Provides, among others, the following methods:

  { public static void main(String[] args) {

  Queue<String> myQ = new LinkedList<String>(); for(int ii=0; ii<args.length; ii++) myQ.offer(args[ii]); while(!myQ.isEmpty()) { String myString = myQ.remove(); System.out.println(myString);

  • Note that Queue is an interface. What classes implement it? Lots!

  }

  Among others: PriorityQueue and LinkedList! (How is

  }

  that possible?)

  } • All the above operations are O(1).

  What is the output of java QueueTester this is a funny little test? Sets

  Overriding equals and hashCode • The Set interface represents the set data structure. public boolean equals(Object x)

  • Must override (not overload!)
  • Does not provide any new methods, but alters behaviour of standard Collection methods:

  public int hashCode()

  • Must override
  • Think of hashCode as giving a “hint” to HashSet where to store an element.

  The connection between equals and hashCode: Duplicates are found using Object’s equals method:

  If x.equals(y), then you must ensure that x.hashCode() = y.hashCode() If !x.equals(y), then you should ensure that x.hashCode() 6= y.hashCode() A Set contains no pair of elements e1 and e2 such that e1.equals(e2).

  • Thus, elements of a Set should make sure equals “makes • sense”.
  • Thus, elements of a Set should make sure equals “makes sense”.
  • The Set interface is implemented by the HashSet class.
  • The Set interface is implemented by the HashSet class.
  • Requires elements that override a special hashCode method.
  • Requires elements that override a special hashCode method.
  • On average, HashSet operations are O(1).
  • On average, HashSet operations are O(1).

Set

  More on equals and hashCode

  • What would make a good definition of equals?
  • What would make a good definition of hashCode?

  Class StudentData {

  SortedSet , which maintains its items in sorted order.

  Duplicates are found using Object’s equals method:

  A Set contains no pair of elements e1 and e2 such that e1.compareTo(e2)==0.

  SortedSets and Comparable

  public int compareTo(E x).

  Sorted Sets

  Iterator is guaranteed to step through its items in its sorted order.

  Set interface has a subinterface,

  String studentID, firstName, lastName, address; public boolean equals(Object x) { if (x == null || x.getClass() != getClass()) return false; return studentID.equals(((StudentData)x).studentID);

  SetTester program What is the output of java SetTester this is a very very very funny test?

  { Set<String> mySet = new HashSet<String>(); for(int ii=0; ii<args.length; ii++) mySet.add(args[ii]); Iterator<String> myIterator = mySet.iterator(); while(myIterator.hasNext()) System.out.println(myIterator.next()); }

  import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class SetTester { public static void main(String[] args)

  Example of a simple class Example usage of

  }

  } public int hashCode() { return Integer.parseInt(studentID); //?? return firstName.length() + lastName.length() + address.length(); //?? }

  }

  • The
  • Elements must be Comparable, i.e. must implement
  • Its
  • Provides the following additional methods, among others:
  • Thus, elements of a Set should make sure equals and compareTo are consistent.
  • The SortedSet interface is implemented by the TreeSet class.
  • On average, TreeSet operations are O(logN), but worst case is O(N).
SortedSet Example usage of

  Maps

  • The Map interface defines the map data structure. It is not a

  SortedSetTester program Collection!

  import java.util.Iterator; import java.util.SortedSet;

  • Provides the following methods, among others:

  import java.util.TreeSet; public class SortedSetTester { public static void main(String[] args)

  { SortedSet<String> mySortedSet = new TreeSet<String>(); for(int ii=0; ii<args.length; ii++) mySortedSet.add(args[ii]); Iterator<String> myIterator = mySortedSet.iterator(); while(myIterator.hasNext()) System.out.println(myIterator.next()); }

  }

  What is the output of java SortedSetTester this is a very very very funny test? Summary

  • The Java Collections API provides ready-made implementations of the various data structures we have seen.
  • Most of the data structures implement the Collection interface.