chapter 11: collection of objects ● in actual programs, always there is need to create and...

62
Chapter 11: Collection of objects In actual programs, always there is need to create and manipulate objects Number of objects is not known at compile time They may grow or shrink We need some utilities to store collection of obejcts Arrays are not a general solution Java provides utility classes which are containers for objects

Upload: laurence-robinson

Post on 13-Jan-2016

219 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Chapter 11: Collection of objects

● In actual programs, always there is need to create and manipulate objects– Number of objects is not known at compile time– They may grow or shrink

● We need some utilities to store collection of obejcts

● Arrays are not a general solution● Java provides utility classes which are containers

for objects

Page 2: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Arrays revisited

● Arrays are efficient, typed and can store primitive types

● Size is fixed (can't grow or shrink)● Arrays are usefull when maximum number of

objects can be gussed.● For more general situations we need to use other

form of containers like Lists, Sets and Maps

Page 3: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Arrays are first-class objects // Arrays of primitives: int[] e; // Null reference int[] f = new int[5]; int[] g = new int[4]; for(int i = 0; i < g.length; i++) g[i] = i*i; int[] h = { 11, 47, 93 }; // Compile error: variable e not initialized: //!System.out.println("e.length=" + e.length); System.out.println("f.length = " + f.length); // The primitives inside the array are // automatically initialized to zero: for(int i = 0; i < f.length; i++) System.out.println("f[" + i + "]=" + f[i]);

// Arrays of objects: Weeble[] a; // Local uninitialized variable Weeble[] b = new Weeble[5]; // Null references Weeble[] c = new Weeble[4]; for(int i = 0; i < c.length; i++) if(c[i] == null) // Can test for null reference c[i] = new Weeble(); // Aggregate initialization: Weeble[] d = { new Weeble(), new Weeble(), new Weeble() }; // Dynamic aggregate initialization: a = new Weeble[] { new Weeble(), new Weeble() }; System.out.println("a.length=" + a.length); System.out.println("b.length = " + b.length); // The references inside the array are // automatically initialized to null: for(int i = 0; i < b.length; i++) System.out.println("b[" + i + "]=" + b[i]); System.out.println("c.length = " + c.length); System.out.println("d.length = " + d.length); a = d; System.out.println("a.length = " + a.length);

Page 4: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Returning an array

● As like any other object, a method can return an array as its result● The method can create array and initialize it● Remember that gaurbage collector takes care of objects on the heap, so it does not matter if the array is created inside a method, when there is no need for that, gaurbage collector destroys it

Page 5: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Returning an array - example public static void main(String[] args) { for(int i = 0; i < 20; i++) { System.out.println( "flavorSet(" + i + ") = "); String[] fl = flavorSet(flavors.length); for(int j = 0; j < fl.length; j++) System.out.println("\t" + fl[j]); monitor.expect(new Object[] { "%% flavorSet\\(\\d+\\) = ", new TestExpression("%% \\t(Chocolate|Strawberry|" + "Vanilla Fudge Swirl|Mint Chip|Mocha Almond " + "Fudge|Rum Raisin|Praline Cream|Mud Pie)", 8) }); } }} ///:~

public class IceCream { private static Test monitor = new Test(); private static Random rand = new Random(); public static final String[] flavors = { "Chocolate", "Strawberry", "Vanilla Fudge Swirl", "Mint Chip", "Mocha Almond Fudge", "Rum Raisin", "Praline Cream", "Mud Pie" }; public static String[] flavorSet(int n) { String[] results = new String[n]; boolean[] picked = new boolean[flavors.length]; for(int i = 0; i < n; i++) { int t; do t = rand.nextInt(flavors.length); while(picked[t]); results[i] = flavors[t]; picked[t] = true; } return results; }

Page 6: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Arrays class

● TO support some operations on arrays, java provoides a utility class named Arrays

● It has methods like:– fill() to fill an array with a value– sort() to sort an array– binarySearch() to search an array for an element– Equals() to test two arrays for having same elements

● Eckel provides Arrays2 class that provides some other usfull operations on arrays like toString(). Study it by yourself.

● We can use System.arrayCopy() to copy contents of one array to another one

Page 7: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Arrays operations example

// Objects: Integer[] u = new Integer[10]; Integer[] v = new Integer[5]; Arrays.fill(u, new Integer(47)); Arrays.fill(v, new Integer(99)); System.out.println("u = " + Arrays.asList(u)); System.out.println("v = " + Arrays.asList(v)); System.arraycopy(v, 0, u, u.length/2, v.length); System.out.println("u = " + Arrays.asList(u)); monitor.expect(new String[] { "i = [47, 47, 47, 47, 47, 47, 47]", "j = [99, 99, 99, 99, 99, 99, 99, 99, 99, 99]", "j = [47, 47, 47, 47, 47, 47, 47, 99, 99, 99]", "k = [47, 47, 47, 47, 47]", "i = [103, 103, 103, 103, 103, 47, 47]", "u = [47, 47, 47, 47, 47, 47, 47, 47, 47, 47]", "v = [99, 99, 99, 99, 99]", "u = [47, 47, 47, 47, 47, 99, 99, 99, 99, 99]" }); }} ///:~

public class CopyingArrays { private static Test monitor = new Test(); public static void main(String[] args) { int[] i = new int[7]; int[] j = new int[10]; Arrays.fill(i, 47); Arrays.fill(j, 99); System.out.println("i = " + Arrays2.toString(i)); System.out.println("j = " + Arrays2.toString(j)); System.arraycopy(i, 0, j, 0, i.length); System.out.println("j = " + Arrays2.toString(j)); int[] k = new int[5]; Arrays.fill(k, 103); System.arraycopy(i, 0, k, 0, k.length); System.out.println("k = " + Arrays2.toString(k)); Arrays.fill(k, 103); System.arraycopy(k, 0, i, 0, k.length); System.out.println("i = " + Arrays2.toString(i));

Page 8: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Comparing arrayspublic class ComparingArrays { private static Test monitor = new Test(); public static void main(String[] args) { int[] a1 = new int[10]; int[] a2 = new int[10]; Arrays.fill(a1, 47); Arrays.fill(a2, 47); System.out.println(Arrays.equals(a1, a2)); a2[3] = 11; System.out.println(Arrays.equals(a1, a2)); String[] s1 = new String[5]; Arrays.fill(s1, "Hi"); String[] s2 = {"Hi", "Hi", "Hi", "Hi", "Hi"}; System.out.println(Arrays.equals(s1, s2)); monitor.expect(new String[] { "true", "false", "true" }); }} ///:~

Page 9: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Sorting arrays

public class StringSorting { public static void main(String[] args) { String[] sa = new String[30]; Arrays2.fill(sa, new Arrays2.RandStringGenerator(5)); System.out.println( "Before sorting: " + Arrays.asList(sa)); Arrays.sort(sa); System.out.println( "After sorting: " + Arrays.asList(sa)); }} ///:~

● This code uses default compareTo of String class (of comparable interface)● Default compareTo for String class uses lexicographic ordering:all uppercase letters first and then all lower case letters

Page 10: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Sorting arrays – different ordering

public class AlphabeticComparator implements Comparator { public int compare(Object o1, Object o2) { String s1 = (String)o1; String s2 = (String)o2; return s1.toLowerCase().compareTo(s2.toLowerCase()); }} ///:~

public class AlphabeticSorting { public static void main(String[] args) { String[] sa = new String[30]; Arrays2.fill(sa, new Arrays2.RandStringGenerator(5)); System.out.println( "Before sorting: " + Arrays.asList(sa)); Arrays.sort(sa, new AlphabeticComparator()); System.out.println( "After sorting: " + Arrays.asList(sa)); }} ///:~

Page 11: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Searching a sorted arraypublic class ArraySearching { public static void main(String[] args) { int[] a = new int[100]; Arrays2.RandIntGenerator gen = new Arrays2.RandIntGenerator(1000); Arrays2.fill(a, gen); Arrays.sort(a); System.out.println( "Sorted array: " + Arrays2.toString(a)); while(true) { int r = gen.next(); int location = Arrays.binarySearch(a, r); if(location >= 0) { System.out.println("Location of " + r + " is " + location + ", a[" + location + "] = " + a[location]); break; // Out of while loop } } }} ///:~

Page 12: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Containers

● In Java container classes are divided to two groups● Collection: a group of individual elements, often with some

rule applied to them: A List must hold the elements in a particular sequence, and a Set cannot have any duplicate elements.

● Map: a group of key-value object pairs. At first glance, this might seem like it ought to be a Collection of pairs, but when you try to implement it that way the design gets awkward, so it’s clearer to make it a separate concept. On the other hand, it’s convenient to look at portions of a Map by creating a Collection to represent that portion. Thus, a Map can return a Set of its keys, a Collection of its values, or a Set of its pairs.

Page 13: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Printing containersimport java.util.*;public class PrintingContainers { private static Test monitor = new Test(); static Collection fill(Collection c) { c.add("dog"); c.add("dog"); c.add("cat"); return c; } static Map fill(Map m) { m.put("dog", "Bosco"); m.put("dog", "Spot"); m.put("cat", "Rags"); return m; } public static void main(String[] args) { System.out.println(fill(new ArrayList())); System.out.println(fill(new HashSet())); System.out.println(fill(new HashMap())); monitor.expect(new String[] { "[dog, dog, cat]", "[dog, cat]", "{dog=Spot, cat=Rags}" }); }} ///:~

Page 14: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Container disadvantages: uknown types

Because the type information is thrown away when you put an object reference into a container, there’s no restriction on the type of object that can be put into your container, even if you mean it to hold only, say, cats. Someone could just as easily put a dog into the container.

Because the type information is lost, the only thing the container knows that it holds is a reference to an object. You must perform a cast to the correct type before you use it.

Page 15: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Inability to control type of objects we put in a containerpublic class Cat { private int catNumber; public Cat(int i) { catNumber = i; } public void id() { System.out.println("Cat #" + catNumber); }}

public class Dog { private int dogNumber; public Dog(int i) { dogNumber = i; } public void id() { System.out.println("Dog #" + dogNumber); }} ///:~

import java.util.*;

public class CatsAndDogs { public static void main(String[] args) { List cats = new ArrayList(); for(int i = 0; i < 7; i++) cats.add(new Cat(i)); // Not a problem to add a dog to cats: cats.add(new Dog(7)); for(int i = 0; i < cats.size(); i++) ((Cat)cats.get(i)).id(); // Dog is detected only at run time }} ///:~

Page 16: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Defining toString() helps to avoid some casts

public class Mouse { private int mouseNumber; public Mouse(int i) { mouseNumber = i; } // Override Object.toString(): public String toString() { return "This is Mouse #" + mouseNumber; } public int getNumber() { return mouseNumber; }} ///:~

public class MouseTrap { static void caughtYa(Object m) { Mouse mouse = (Mouse)m; // Cast from Object System.out.println("Mouse: " + mouse.getNumber()); }} ///:~

public class WorksAnyway { private static Test monitor = new Test(); public static void main(String[] args) { List mice = new ArrayList(); for(int i = 0; i < 3; i++) mice.add(new Mouse(i)); for(int i = 0; i < mice.size(); i++) { // No cast necessary, automatic // call to Object.toString(): System.out.println("Free mouse: " + mice.get(i)); MouseTrap.caughtYa(mice.get(i)); } monitor.expect(new String[] { "Free mouse: This is Mouse #0", "Mouse: 0", "Free mouse: This is Mouse #1", "Mouse: 1", "Free mouse: This is Mouse #2", "Mouse: 2" }); }} ///:~

Page 17: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Making a type conscious ArrayList

public class MouseList { private List list = new ArrayList(); public void add(Mouse m) { list.add(m); } public Mouse get(int index) { return (Mouse)list.get(index); } public int size() { return list.size(); }} ///:~

public class MouseListTest { private static Test monitor = new Test(); public static void main(String[] args) { MouseList mice = new MouseList(); for(int i = 0; i < 3; i++) mice.add(new Mouse(i)); for(int i = 0; i < mice.size(); i++) MouseTrap.caughtYa(mice.get(i)); monitor.expect(new String[] { "Mouse: 0", "Mouse: 1", "Mouse: 2" }); }} ///:~

Page 18: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Moving through a container elements using Iterators

Containers lets us traversing their elements sequentially by using an Iterator object

Iterator related Opeartions:1- Ask a container to hand you an Iterator using a method called iterator( ). This Iterator will be ready to return the first element in the sequence on your first call to its next( ) method. 2- Get the next object in the sequence with next( ). 3- See if there are any more objects in the sequence with hasNext( ). 4- Remove the last element returned by the iterator with remove( ).

Page 19: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Iterators usage examples

public class CatsAndDogs2 { private static Test monitor = new Test(); public static void main(String[] args) { List cats = new ArrayList(); for(int i = 0; i < 7; i++) cats.add(new Cat(i)); Iterator e = cats.iterator(); while(e.hasNext()) ((Cat)e.next()).id(); }} ///:~

public class Printer { static void printAll(Iterator e) { while(e.hasNext()) System.out.println(e.next()); }} ///:~

Page 20: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Container taxonomy

Page 21: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Coding for interfaces (not implementations)

It is a good programming practice to write codes to work with interfaces.

This way the only place you care about implementation is at the point of creation:

List x = new LinkedList();

In other parts of code, you work with List. This has the benefit that if you decide to change implementation (for example to ArrayList), other parts of code is not affected

Page 22: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Coding for interfaces (not implementations)

It is a good programming practice to write codes to work with interfaces.

This way the only place you care about implementation is at the point of creation:

List x = new LinkedList();

In other parts of code, you work with List. This has the benefit that if you decide to change implementation (for example to ArrayList), other parts of code is not affected

Page 23: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

A collection examplepublic class SimpleCollection { private static Test monitor = new Test(); public static void main(String[] args) { // Upcast because we just want to // work with Collection features Collection c = new ArrayList(); for(int i = 0; i < 10; i++) c.add(Integer.toString(i)); Iterator it = c.iterator(); while(it.hasNext()) System.out.println(it.next()); monitor.expect(new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }); }} ///:~

Page 24: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Collection functionality

Page 25: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Collection functionality (Cont.)

Page 26: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Collection functionality - example Collection c = new ArrayList(); Collections2.fill(c, Collections2.countries, 5); c.add("ten"); c.add("eleven"); System.out.println(c); // Make an array from the List: Object[] array = c.toArray(); // Make a String array from the List: String[] str = (String[])c.toArray(new String[1]); // Find max and min elements; this means // different things depending on the way // the Comparable interface is implemented: System.out.println("Collections.max(c) = " + Collections.max(c)); System.out.println("Collections.min(c) = " + Collections.min(c)); // Add a Collection to another Collection Collection c2 = new ArrayList(); Collections2.fill(c2, Collections2.countries, 5); c.addAll(c2);

// Remove all components that are // in the argument collection: c.removeAll(c2); System.out.println(c); c.addAll(c2); System.out.println(c); // Is a Collection in this Collection? System.out.println( "c.containsAll(c2) = " + c.containsAll(c2)); Collection c3 = ((List)c).subList(3, 5); // Keep all the elements that are in both // c2 and c3 (an intersection of sets): c2.retainAll(c3); System.out.println(c); // Throw away all the elements // in c2 that also appear in c3: c2.removeAll(c3);

Page 27: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

List functionality

Page 28: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

List functionality example

public static void basicTest(List a) { a.add(1, "x"); // Add at location 1 a.add("x"); // Add at end // Add a collection: a.addAll(fill(new ArrayList())); // Add a collection starting at location 3: a.addAll(3, fill(new ArrayList())); b = a.contains("1"); // Is it in there? // Is the entire collection in there? b = a.containsAll(fill(new ArrayList())); // Lists allow random access, which is cheap // for ArrayList, expensive for LinkedList: o = a.get(1); // Get object at location 1 i = a.indexOf("1"); // Tell index of object b = a.isEmpty(); // Any elements inside? it = a.iterator(); // Ordinary Iterator lit = a.listIterator(); // ListIterator lit = a.listIterator(3); // Start at loc 3 i = a.lastIndexOf("1"); // Last match

a.remove(1); // Remove location 1 a.remove("3"); // Remove this object a.set(1, "y"); // Set location 1 to "y" // Keep everything that's in the argument // (the intersection of the two sets): a.retainAll(fill(new ArrayList())); // Remove everything that's in the argument: a.removeAll(fill(new ArrayList())); i = a.size(); // How big is it? a.clear(); // Remove all elements }

Page 29: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

List functionality example (cont.)

public static void iterMotion(List a) { ListIterator it = a.listIterator(); b = it.hasNext(); b = it.hasPrevious(); o = it.next(); i = it.nextIndex(); o = it.previous(); i = it.previousIndex(); }

Page 30: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

List functionality example (cont.)

public static void iterManipulation(List a) { ListIterator it = a.listIterator(); it.add("47"); // Must move to an element after add(): it.next(); // Remove the element that was just produced: it.remove(); // Must move to an element after remove(): it.next(); // Change the element that was just produced: it.set("47"); }

Page 31: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

List functionality example (cont.) // There are some things that only LinkedLists can do: public static void testLinkedList() { LinkedList ll = new LinkedList(); fill(ll); System.out.println(ll); // Treat it like a stack, pushing: ll.addFirst("one"); ll.addFirst("two"); System.out.println(ll); // Like "peeking" at the top of a stack: System.out.println(ll.getFirst()); // Like popping a stack: System.out.println(ll.removeFirst()); System.out.println(ll.removeFirst()); // Treat it like a queue, pulling elements // off the tail end: System.out.println(ll.removeLast()); // With the above operations, it's a dequeue! System.out.println(ll); }

Page 32: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Making a stack from a linkedListpublic class StackL { private LinkedList list = new LinkedList(); public void push(Object v) { list.addFirst(v); } public Object top() { return list.getFirst(); } public Object pop() { return list.removeFirst(); } public static void main(String[] args) { StackL stack = new StackL(); for(int i = 0; i < 10; i++) stack.push(Collections2.countries.next()); System.out.println(stack.top()); System.out.println(stack.top()); System.out.println(stack.pop()); System.out.println(stack.pop()); System.out.println(stack.pop()); monitor.expect(new String[] { "CHAD", "CHAD", "CHAD", "CENTRAL AFRICAN REPUBLIC", "CAPE VERDE" }); }} ///:~

Page 33: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Making a queue from a linkedListpublic class Queue { private LinkedList list = new LinkedList(); public void put(Object v) { list.addFirst(v); } public Object get() { return list.removeLast(); } public boolean isEmpty() { return list.isEmpty(); } public static void main(String[] args) { Queue queue = new Queue(); for(int i = 0; i < 10; i++) queue.put(Integer.toString(i)); while(!queue.isEmpty()) System.out.println(queue.get()); monitor.expect(new String[] { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }); }} ///:~

Page 34: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Set Functionality

Page 35: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Set Functionality example public static void main(String[] args) { test(new HashSet()); test(new TreeSet()); test(new LinkedHashSet()); monitor.expect(new String[] { "HashSet", "[one, two, five, four, three, seven, six]", "[one, two, five, four, three, seven, six]", "s.contains(\"one\"): true", "TreeSet", "[five, four, one, seven, six, three, two]", "[five, four, one, seven, six, three, two]", "s.contains(\"one\"): true", "LinkedHashSet", "[one, two, three, four, five, six, seven]", "[one, two, three, four, five, six, seven]", "s.contains(\"one\"): true" }); }}

public class Set1 { private static Test monitor = new Test(); static void fill(Set s) { s.addAll(Arrays.asList( "one two three four five six seven".split(" "))); } public static void test(Set s) { // Strip qualifiers from class name: System.out.println( s.getClass().getName().replaceAll("\\w+\\.", "")); fill(s); fill(s); fill(s); System.out.println(s); // No duplicates! // Add another set to this one: s.addAll(s); s.add("one"); s.add("one"); s.add("one"); System.out.println(s); // Look something up: System.out.println("s.contains(\"one\"): " + s.contains("one")); }

Page 36: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Sorted set

System.out.println(low); System.out.println(high); System.out.println(sortedSet.subSet(low, high)); System.out.println(sortedSet.headSet(high)); System.out.println(sortedSet.tailSet(low)); monitor.expect(new String[] { "[eight, five, four, one, seven, six, three, two]", "eight", "two", "one", "two", "[one, seven, six, three]", "[eight, five, four, one, seven, six, three]", "[one, seven, six, three, two]" }); }}

public class SortedSetDemo { private static Test monitor = new Test(); public static void main(String[] args) { SortedSet sortedSet = new TreeSet(Arrays.asList( "one two three four five six seven eight".split(" "))); System.out.println(sortedSet); Object low = sortedSet.first(), high = sortedSet.last(); System.out.println(low); System.out.println(high); Iterator it = sortedSet.iterator(); for(int i = 0; i <= 6; i++) { if(i == 3) low = it.next(); if(i == 6) high = it.next(); else it.next(); }

Page 37: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Map functionality

Page 38: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Map usage exampleclass Counter { int i = 1; public String toString() { return Integer.toString(i); }}

public class Statistics { private static Random rand = new Random(); public static void main(String[] args) { Map hm = new HashMap(); for(int i = 0; i < 10000; i++) { // Produce a number between 0 and 20: Integer r = new Integer(rand.nextInt(20)); if(hm.containsKey(r)) ((Counter)hm.get(r)).i++; else hm.put(r, new Counter()); } System.out.println(hm); }} ///:~

Page 39: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Sorted mappublic class SimplePairGenerator implements MapGenerator { public Pair[] items = { new Pair("one", "A"), new Pair("two", "B"), new Pair("three", "C"), new Pair("four", "D"), new Pair("five", "E"), new Pair("six", "F"), new Pair("seven", "G"), new Pair("eight", "H"), new Pair("nine", "I"), new Pair("ten", "J") }; private int index = -1; public Pair next() { index = (index + 1) % items.length; return items[index]; } public static SimplePairGenerator gen = new SimplePairGenerator();}

Object low = sortedMap.firstKey(), high = sortedMap.lastKey(); System.out.println(low); System.out.println(high); Iterator it = sortedMap.keySet().iterator(); for(int i = 0; i <= 6; i++) { if(i == 3) low = it.next(); if(i == 6) high = it.next(); else it.next(); } System.out.println(low); System.out.println(high); System.out.println(sortedMap.subMap(low, high)); System.out.println(sortedMap.headMap(high)); System.out.println(sortedMap.tailMap(low)); monitor.expect(new String[] { "{eight=H, five=E, four=D, nine=I, one=A, seven=G," + " six=F, ten=J, three=C, two=B}", "eight", "two", "nine", "ten", "{nine=I, one=A, seven=G, six=F}", "{eight=H, five=E, four=D, nine=I, " + "one=A, seven=G, six=F}", "{nine=I, one=A, seven=G, six=F, " + "ten=J, three=C, two=B}" }); }}

public class SortedMapDemo { private static Test monitor = new Test(); public static void main(String[] args) { TreeMap sortedMap = new TreeMap(); Collections2.fill( sortedMap, SimplePairGenerator.gen, 10); System.out.println(sortedMap);

Page 40: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Hashing

● Hashing is a common way to build lookup tables● For each key a hash value is calculated● Objects are inserted in locations that are specified by their hash value● For lookup, again hash code is used to find the place the obejct is in

● The root class Object in java defines a hashCode method which simply returns address of the object as hashCode● It is in-appropriate in many situations (e.g. two keys may have same value but have different addresses!)● Subclasses like String overdies hashCode to have appropriate behavior● For user-defined classes therefore we need to implement hasCode● HashMap also uses equals() method. So for user defined classes we need to overide equals() too.

Page 41: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Example of defining hashCode and equals

public class Groundhog { int number; public Groundhog(int n) {number=n; } public int hashCode() { return number; } public boolean equals(Object o) { return (o instanceof Groundhog2)

&& (number == ((Groundhog2)o).number);

}

}

Page 42: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Why hashing?

● Hashing improve lookup performance● Without hashing, to implement a lookup table, we may use a linked list or a sorted linked list● Those structures in average has worst performance than hash tables for implementing lookup tables● In the book a SlowMap is defined that demonstrates how to implement a Map using ArrayList. It is discussed that this solution is not appropriate because of slow performance ● Also in the book, a SimpleHashMap is defined. Study it and be sure that you understand how it works

Page 43: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

HashMap performance

● Normally java HashMap has good performance which is acceptable for many applications● However, we can control the performance● To do this when creating a HashMap, we can specify “load factor” threshold. Load factor is size/capactiy. When load factor reaches the threshold, HashMap is expanded and all entries is rehashed. This way collisions will be reduced.

new hashMap(0.5); // default load factor is 0.75

Page 44: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Guidelines for hashCode() implementation

1. Store some constant nonzero value, say 17, in an int variable called result.

2. For each significant field f in your object (each field taken into account by the equals( ), that is), calculate an int hash code c for the

boolean c = (f ? 0 : 1)

byte, char, short, or int c = (int)f

...

3. Combine the hash code(s) computed above:result = 37 * result + c;

4. Return result.

5. Look at the resulting hashCode( ) and make sure that equal instances have equal hash codes.

Page 45: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Reference classes● The Java 2 platform introduced the java.lang.ref package, which contains classes that allow you to refer to objects without pinning them in memory.

● We have SoftReference, WeakReference, and PhantomReference classes

● To understand these classes first we need to define the meaning of “reachable”:

Strongly reachable: An object that can be accessed by a strong reference.

Softly reachable: An object that is not strongly reachable and can be accessed through a soft reference.

Weakly reachable: An object that is not strongly or softly reachable and can be accessed through a weak reference.

Phantomly reachable: An object that is not strongly, softly, or weakly reachable, has been finalized, and can be accessed through a phantom reference.

Page 46: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Reference classes – SoftRefrence class

● A typical use of the SoftReference class is for a memory-sensitive cache.

● The idea of a SoftReference is that you hold a reference to an object with the guarantee that all of your soft references will be cleared before the JVM reports an out-of-memory condition.

● The key point is that when the garbage collector runs, it may or may not free an object that is softly reachable. Whether the object is freed depends on the algorithm of the garbage collector as well as the amount of memory available while the collector is running.

Page 47: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Reference classes – SoftRefrence class

SoftReference sr =

new SoftReference (new Employee ());

Page 48: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

SoftRefrence example – image cacheSoftReference sr = null;

// ... Sometime later in a drawing method.

Image im = (sr == null) ? null : (Image) (sr.get());if (im == null) { im = getImage (getCodeBase(), "truck1.gif"); sr = new SoftReference (im);}// Draw the image.

// Later, clear the strong reference to the Image subclass object.// That is done, so -- assuming no other strong reference exists -- // the only reference to the Image subclass object is a soft // reference. Eventually, when the garbage collector notes that it // is running out of heap memory, it can clear that soft reference // (and eventually remove the object).

im = null;

Page 49: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

SoftRefrence example – demonstrating the usage of ReferenceQueueimport java.lang.ref.*;class Employee{ private String name; Employee (String name) { this.name = name; } public String toString () { return name; }}

class SoftReferenceDemo{ public static void main (String [] args) { // Create two Employee objects that are strongly reachable from e1 // and e2.

Employee e1 = new Employee ("John Doe"); Employee e2 = new Employee ("Jane Doe");

// Create a ReferenceQueue object that is strongly reachable from q.

ReferenceQueue q = new ReferenceQueue ();

// Create a SoftReference array with room for two references to // SoftReference objects. The array is strongly reachable from sr.

SoftReference [] sr = new SoftReference [2];

Page 50: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

SoftRefrence example – demonstrating the usage of ReferenceQueue (cont.)

// Assign a SoftReference object to each array element. That object // is strongly reachable from that element. Each SoftReference object // encapsulates an Employee object that is referenced by e1 or e2 (so // the Employee object is softly reachable from the SoftReference // object), and associates the ReferenceQueue object, referenced by // q, with the SoftReference object. sr [0] = new SoftReference (e1, q); sr [1] = new SoftReference (e2, q);

// Remove the only strong references to the Employee objects. e1 = null; e2 = null;

// Poll reference queue until SoftReference object arrives. Reference r; while ((r = q.poll ()) == null) { System.out.println ("Polling reference queue");

// Suggest that the garbage collector should run.

System.gc (); }

Page 51: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

SoftRefrence example – demonstrating the usage of ReferenceQueue (cont.)

// Identify the SoftReference object whose soft reference was // cleared, and print an appropriate message.

if (r == sr [0]) System.out.println ("John Doe Employee object's soft reference " + "cleared"); else System.out.println ("Jane Doe Employee object's soft reference " + "cleared");

// Attempt to retrieve a reference to the Employee object.

Employee e = (Employee) r.get ();

// e will always be null because soft references are cleared before // references to their containing SoftReference objects are queued // onto a reference queue.

if (e != null) System.out.println (e.toString ()); }}

Page 52: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

SoftRefrence example – demonstrating the usage of ReferenceQueue (cont.)

Polling reference queuePolling reference queuePolling reference queuePolling reference queuePolling reference queuePolling reference queuePolling reference queuePolling reference queuePolling reference queuePolling reference queuePolling reference queuePolling reference queuePolling reference queueJane Doe Employee object's soft reference cleared

Program output

Page 53: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

WeakReference● When you initialize a WeakReference object, you store a referent's reference in that object.

● The object contains a weak reference to the referent, and the referent is weakly reachable if there are no other references, apart from weak references, to that referent.

● If heap memory is running low, the garbage collector locates weakly reachable objects and clears their weak references -- by calling WeakReference's inherited clear() method.

● Assuming no other references point to those referents, the referents is gaurbage collected

Page 54: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

WeakReference - exampleClass WeakReferenceDemo{public static void main (String [] args){ // Create a String object that is strongly reachable from key.

String key = new String ("key"); /* Note: For this program, you cannot say String key = "key";. You cannot do that because (by itself), "key" is strongly referenced from an internal constant pool data structure (that I will discuss in a future article). There is no way for the program to nullify that strong reference. As a result, that object will never be garbage collected, and the polling loop will be infinite. */

// Create a ReferenceQueue object that is strongly reachable from q.

ReferenceQueue q = new ReferenceQueue ();

Page 55: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

WeakReference – example (cont.)// Create a WeakReference object that is strongly reachable from wr.// The WeakReference object encapsulates the String object that is// referenced by key (so the String object is weakly-reachable from// the WeakReference object), and associates the ReferenceQueue// object, referenced by q, with the WeakReference object.

WeakReference wr = new WeakReference (key, q);

// Create an Object object that is strongly reachable from value.

Object value = new Object ();

// Create a Hashtable object that is strongly reachable from ht.

Hashtable ht = new Hashtable ();

// Place the WeakReference and Object objects in the hash table.

ht.put (wr, value);

Page 56: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

WeakReference – example (cont.) // Remove the only strong reference to the String object. key = null; // Poll reference queue until WeakReference object arrives. Reference r; while ((r = q.poll ()) == null) { System.out.println ("Polling reference queue"); // Suggest that the garbage collector should run. System.gc (); } // Using strong reference to the Reference object, remove the entry // from the Hashtable where the WeakReference object serves as that // entry's key. value = ht.remove (r); // Remove the strong reference to the Object object, so that object // is eligible for garbage collection. Although not necessary in this // program, because we are about to exit, imagine a continuously- // running program and that this code is in some kind of long-lasting // loop. value = null; }}

Page 57: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

WeakReference (cont.)

● WeakHashMap class in Java implements what is demonstrated in the previous example

● See the example in the book for the usage of WeakHashMap

Page 58: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Choosing a Container

● We have seen a number of containers. We should know in what situations to use each of them● We now when we need a List or a Set or a Map

●List is used when the order of elements are important●Set is used when we don't care about order but we want to be sure there is no repeatition●Map is used for making associations between keys and values (lookup tables)

Page 59: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Choosing between List implementations

Page 60: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Choosing between Set implementations

Page 61: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Choosing between Maps

Page 62: Chapter 11: Collection of objects ● In actual programs, always there is need to create and manipulate objects – Number of objects is not known at compile

Other discussions

The following is left for your self study (it is not for ignoring, because of time limit we can't discuss them in class)

● Sorting and searching lists● Utilities (finding minimum/maximum in a collection, rotating elements, filling collections, etc.)● Making a collection or Map unmodifiable● Synchronizing a collection or Map● Legacy classes (Vector and Stack)