Java Notes (2) -- Interfaces, Inheritance, Iterators, Collections Framework


Additional Java topics related to this course:

  1. Java interfaces
  2. Java generics
  3. Java iterators
  4. Java collections framework

1. Java Interfaces


2. Java Inheritance


3. Java Generics


4. The Java Collections Framework

  • Interfaces

    Here is a hierarchy of some of the interfaces, from The Java Tutorial Collections Trail

  • The Collection interface

    Rather than pass around a Set or a List reference to a collection, you can write the most general code by working with Collection. For example:

        Collection<String> s = new HashSet<String>();
     
        ... s.add( some String ) ...
     
        System.out.println(s);
    
    since add() is a method of Collection.

    Here is (part of) the interface:

    public interface Collection<T> extends Iterable<T> {
        // Basic Operations
        int size();
        boolean isEmpty();
        boolean contains(E element);
        boolean add(E element);    
        boolean remove(E element); 
        Iterator<T> iterator();
    
        // Bulk Operations
        boolean containsAll(Collection<T> c);
        boolean addAll(Collection<T> c);    
        boolean removeAll(Collection<T> c); 
        boolean retainAll(Collection<T> c); 
        void clear();                            
    
        // Array Operations
        E[] toArray();
        E[] toArray(E a[]);
    }
    

    size and isEmpty are obvious, as are add and remove. Note: remove will remove a single instance of the Object -- doesn't matter for Sets but does for Lists.

  • Iterators
  • Iterators and For-loops
  • Exercise: Write code to delete all strings beginning with the letter 'A' or 'a' from a collection of Strings. Use the forEach construction (with :) when iterating through a for loop to print out the results at the end.

  • The Set Interface

    A Set is a Collection that cannot contain duplicate elements. Set has exactly the same interface as Collection -- it adds nothing new. The boolean returns on add and remove indicate if the element was added or removed.

    There are two implementations of Set provided. HashSet stores its elements in a hash table. TreeSet stores its elements in a red-black tree (it implements SortedSet). The former is more efficient; the latter stores its elements in sorted order. Both will be covered in CSC 403.

    The following example is taken from The Java Tutorial.

    import java.util.*;
    
    public class FindDups {
        public static void main(String args[]) {
            Set<String> s = new HashSet<String>();
            for (int i=0; i<args.length; i++)
                if (!s.add(args[i]))
                    System.out.println("Duplicate detected: "+args[i]);
    
            System.out.println(s.size()+" distinct words detected: "+s);
        }
    }
    
    From the input line:
    % java FindDups i came i saw i left
    
    we get output
    Duplicate: i
    Duplicate: i
    4 distinct words: [came, left, saw, i]
    
    Change the HashSet to a TreeSet and the words will come out in alphabetic order.

  • The List Interface

    A List is an ordered collection. This interface adds some new functionality to Collection, such as:

    Here is the interface:
    public interface List<T> extends Collection {
        /* inherited from Collection:
           boolean contains(T element);
           boolean add(T element);    
           boolean remove(T element); 
           Iterator<T> iterator();
        */
        // Positional Access
        T get(int index);
        T set(int index, T element);
        void add(int index, T element);     
        T remove(int index);                
        abstract boolean addAll(int index, Collection c);
    
        // Search
        int indexOf(T o);
        int lastIndexOf(T o);
    
        // Iteration
        ListIterator listIterator();
        ListIterator listIterator(int index);
    
        // Range-view
        List subList(int from, int to);
    }
    

    There are two implementations provided, ArrayList and LinkedList. We will discuss these later in the quarter.

    The Collection operations are pretty obvious. remove removes only the first occurence of an element. add and addAll add to the end of the list.

    get, set, add, and remove are pretty obvious. Note the additional overload of addAll.

    Here is an example, from The Java Tutorial:

    // swap two elements in a list
    private static void swap(List<T> a, int i, int j) {
        T tmp = a.get(i);
        a.set(i, a.get(j));
        a.set(j, tmp);
    }
    
  • Iteration

    The iterator returned by iterator is fancier than a regular one from a generic Collection. It is a ListIterator with the interface:

    public interface ListIterator<T> extends Iterator<T> {
        boolean hasNext();
        T next();
    
        boolean hasPrevious();
        T previous();
    
        int nextIndex();
        int previousIndex();
    
        void remove();      
        void set(T o); 
        void add(T o); 
    }
    

    Note that you can not only remove elements but also set an element at the current position and add an element at the current position without messing up the iterator.

    Collection implementations

    Implementation Interface
    HashSet Set
    TreeSet SortedSet
    ArrayList List
    LinkedList List
    HashMap Map
    TreeMap SortedMap

    The constructors for these classes have a variety of arguments, to set initial capacities, to copy other collections, to provide Comparators, etc.


  • The Map Interface

    A Map maps keys to values. No duplicate keys allowed. One value per key. Maps are not Iterable.

    Here is the interface

    public interface Map<K,V> {
        // Basic Operations
        V put(K key, V value);
        V get(K key);
        V remove(K key);
        boolean containsKey(K key);
        boolean containsValue(V value);
        int size();
        boolean isEmpty();
    
        // Bulk Operations
        void putAll(Map<K,V> t);
        void clear();
    
        // Collection Views
        public Set<K> keySet();
        public Collection<V> values();
        public Set<Map.Entry<K,V>> entrySet();
    
        // Interface for entrySet elements
        public interface Entry<K1,V1> {
            K1 getKey();
            V1 getValue();
            V1 setValue(Object value);
        }
    }
    

    There are two implementations. HashMap uses a hash table; TreeMap uses a red-black tree. We will study these during the quarter. The former is more efficient; the latter keeps its collections ordered.

    If you are familiar with any type of associative table (such as a Python dictionary), the methods put, get, remove, containsKey and containsValue are straightforward.

    Simple example

    Here is an example from The Java Tutorial that counts the frequency of words on the command line.

    import java.util.*;
    
    public class Freq {
    
        public static void main(String args[]) {
            Map<String,Integer> m = new HashMap<String,Integer>();
    
            // Initialize frequency table from command line
            for (int i=0; i<args.length; i++) {
                Integer freq = m.get(args[i]);
                if (freq == null)
    	        m.put(args[i], 1);
    	    else
    	        m.put(args[i], freq+1);
            }
            System.out.println(m.size()+" distinct words detected:");
            System.out.println(m);
        }
    }
    

    Here is a sample run:

    % java Freq if it is to be it is up to me to delegate
    
    8 distinct words detected:
    {to=3, me=1, delegate=1, it=2, is=2, if=1, be=1, up=1}
    

    Want the output sorted by key? Just replace the HashMap with TreeMap.

    The method keySet gives a way to iterate/interrogate/whatever keys. values does the same for values. entrySet gives a Set whose values are of type Map.Entry. This gives a neat way to change values for keys.

    To iterate over keys of Strings, try

    for ( Iterator<String> i = m.keySet().iterator(); i.hasNext(); )
        System.out.println(i.next());
    

    Similar code works for values.

    Suppose you want to iterate through a map whose values are all Integers and increment each one. Try this:

    for ( Iterator<Map.Entry<Integer,Integer>> i = m.entrySet().iterator(); i.hasNext() ) {
        Map.Entry e = i.next();
        e.setValue( (e.getValue()).intValue() + 1 );
    }
    
  • Using Collections involving Hashing and Trees
  • Hashing
  • Trees