Additional Java topics related to this course:
public interface <name> {
<body>
}
public class <classname> implements <interfacename> {
<method and field definitions>
// Functionalities of any class that is drivable
public interface Drivable
{
public void Drive(int miles); // NO method body
public void shiftGear(int newg); // NO method body
}
// A class which has Drivable functionalities
public class Car implements Drivable
{
...
/* method */
public Car() {...} // constructor
public void Drive(int miles)
{
// actual body of the method
}
public void shiftGear(int newg)
{
// actual body of the method
}
}
// Another class which has Drivable functionalities
public class ToyCar implements Drivable
{
...
/* method */
public ToyCar() {...} // constructor
public void Drive(int miles)
{
// actual body of the method
}
// ToyCar usually has no gear -- this method is not
// applicable. But STILL we must write the method,
// an empty method
public void shiftGear(int newg)
{}
}
static void main(String[] args)
{
Car c = new Car(); // object instantiation in a usual way
c.addFuel(5.0); // invoke a Car method
Drivable d = new Car(); // A Car object pointed by a Drivable reference
// d.addFuel(5.0); // ILLEGAL -- Car methods are NOT accessible
// through interface reference
((Car) d).addFuel(5.0); // LEGAL -- need to cast interface to a class
// Drivable d2 = new Drivable(); // ILLEGAL -- no instance of interface
// Car c2 = new Drivable(); // ditto
public interface MassMeasurable
{
public double volume();
}
public class <class1> extends <class2> {
<body>
}
class Employee {
// protected members can be used in subclasses
protected String name, ssn;
public Employee() { }
public Employee(String name, String ssn) {
this.name = name;
this.ssn = ssn;
}
public String getName() {
return name;
}
public String getSsn() {
return ssn;
}
public String toString() {
return name + " " + ssn;
}
}
class HourlyEmployee extends Employee {
private double hourlyWage;
public HourlyEmployee(String name, String ssn, double wage) {
this.name = name;
this.ssn = ssn;
hourlyWage = wage;
}
public double getWage() {
return hourlyWage;
}
public String toString() {
return super.toString() + ", wage " + hourlyWage;
}
public static void main(String[ ] args) {
HourlyEmployee emp = new HourlyEmployee("Joe", "111-11-1111", 20.00);
System.out.println(emp.getName() + " toString is " + emp);
}
}
toString() method above
Object)
has a superclass
Object
equals is one of the methods defined
in Object:
public boolean equals(Object o)
equals for
any user-defined class, we need to define it as follows:
public class Employee {
//....
public boolean equals(Object o) {
if (obj == null || obj.getClass() != this.getClass())
return false;
else {
Employee that = (Employee) obj; // type-cast Object to Employee
return this.name.equals(that.name) &&
this.ssn.equals(that.ssn);
}
//...
}
public class Pair<K,V> {
private K key;
private V value;
public void set(K parm1, V parm2) {
key = parm1;
value = parm2;
}
public K getKey( ) { return key; }
public V getValue( ) { return value; }
public String toString( ) {
return "[" + key + ", " + value + "]";
}
}
Comparable<T> interface
public interface Comparable<T> {
public int compareTo(T o);
}
obj1.compareTo(obj2):
obj1 <
obj2
obj1 equals
obj2
obj1 >
obj2
String s1 = "data", s2 = "structures",
s3 = "computer", s4 = "computer";
System.out.println(s1.compareTo(s2)); // a positive number
System.out.println(s2.compareTo(s3)); // a negative number
System.out.println(s3.compareTo(s4)); // zero
compareTo requires its parameter to
implement the Comparable interface
extends,
and then a supertype
public class Pair<K, V extends Number> {
private K key;
private V value;
public void set(K parm1, V parm2) {
key = parm1;
value = parm2;
}
public K getKey( ) { return key; }
public V getValue( ) { return value; }
public String toString( ) {
return "[" + key + ", " + value + "]";
}
}
Pair<String, Integer> p = new Pair<String,Integer>( ); // ok Pair<String, Number> p2 = new Pair<String,Number>( ); // ok Pair<String, List> p3 = new Pair<String,List>( ); // won't compile
Iterable interface
// there's more, but we'll ignore for now
public interface Iterable<T> {
public Iterator<T> iterator( );
}
public interface Iterator<T> {
public boolean hasNext( );
public T next( );
public void remove( ); // ignore for now
}
Iterable in order to use it in a
ForEach construction.
for (<Object> o : <iterable-object>) {
...
}
iterable-object must be an object whose
class that implements Iterable
Iterator method is called initially
hasNext and next methods
determine how long the loop runs, and on what objects
Iterable. For example,
String names[ ] = {"Joe", "Jane", "Mary"};
// arrays are Iterable
for (String name : names)
if (name.charAt(0) == 'J')
System.out.println(name); // prints "Joe" and "Jane"
Here is a hierarchy of some of the interfaces, from The Java Tutorial Collections Trail
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.
public interface Iterator<T> {
boolean hasNext();
E next();
void remove();
}
(also, see Ex1.java regarding iterators and arrays)
The remove method removes the last element returned by next; it may be called only once per call to next (else an exception is thrown).
for (<type> <var> : <collection>) {
<body>
}
public void printSet(Set<T> items) {
for (T item : items)
System.out.println(item);
}
forEach construction (with :)
when iterating through a for loop to print out the results at the end.
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 leftwe 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.
A List is an ordered collection. This interface adds some new functionality to Collection, such as:
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);
}
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.
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.
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 );
}
HashMap and HashSet classes require
that data stored in them belong to a class with a hashCode
method, and an equals method. Here are these methods' signatures:
public int hashCode( ); public boolean equals(Object o);
// THIS CODE DOES NOT WORK
import java.util.*;
class MyInteger {
private int x;
public MyInteger(int i) {
x = i;
}
public int intValue( ) {
return x;
}
}
public class MapExample {
public static void main(String args[ ]) {
HashMap<MyInteger, String> m = new HashMap<MyInteger, String>( );
m.put(new MyInteger(1), "a");
m.put(new MyInteger(2), "b");
m.put(new MyInteger(3), "c");
System.out.println(m.get(new MyInteger(1)));
System.out.println(m.get(new MyInteger(2)));
System.out.println(m.get(new MyInteger(3)));
}
}
HashMap, the Key class must have
hashCode and equals methods; otherwise the Key
cannot be found in the Map.
TreeSet and TreeMap classes are implemented
using trees.
In order to keep data in order, Java requires that data stored in a tree
must implement the Comparable interface.
// THIS CODE THROWS AN EXCEPTION
import java.util.*;
class MyInteger {
private int x;
public MyInteger(int i) {
x = i;
}
public int intValue( ) {
return x;
}
public String toString( ) { return " " + x; }
}
public class TreeExample {
public static void main(String args[ ]) {
TreeSet<MyInteger> t = new TreeSet<MyInteger>( );
t.add(new MyInteger(1));
t.add(new MyInteger(1));
t.add(new MyInteger(2));
t.add(new MyInteger(3));
t.remove(new MyInteger(3));
System.out.println(t);
System.out.println(t.contains(new MyInteger(1)));
System.out.println(t.contains(new MyInteger(2)));
}
}