Presentation is loading. Please wait.

Presentation is loading. Please wait.

11: Holding Your Objects Introduction to containers Container disadvantage: unknown type Iterators Container taxonomy Collection functionality List functionality.

Similar presentations


Presentation on theme: "11: Holding Your Objects Introduction to containers Container disadvantage: unknown type Iterators Container taxonomy Collection functionality List functionality."— Presentation transcript:

1 11: Holding Your Objects Introduction to containers Container disadvantage: unknown type Iterators Container taxonomy Collection functionality List functionality Set functionality Map functionality

2 Introduction to containers Container classes are one of the most powerful tools for raw development because they significantly increase your programming muscle. Collection: a group of individual elements. –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. –Key must be unique

3

4 import java.util.*; public class PrintingContainers { static Collection fill(Collection c) { c.add("dog"); c.add("dog");.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())); } } ///:~toString equals hashCode [dog, dog, cat] [dog, cat] {dog=Spot, cat=Rags}

5 Container disadvantage:unknown type When you put an object into a container, the object is upcasted to Object, and therefore the type information is lost. 1.Consequently, there ’ s no restriction on the type of object that can be put into your container, for example, you mean the container to hold only, say, cats. Someone could just as easily put a dog into it. 2.Since the container only knows what it holds is a reference to an object. You must perform a downcast to the correct type before you use it.

6 Container disadvantage:unknown type public class Cat { private int catNumber; Cat(int i) { catNumber = i; } void print() { System.out.println("Cat #" + catNumber); } ///:~ //: c09:Dog.java public class Dog { private int dogNumber; Dog(int i) { dogNumber = i; } void print() { System.out.println("Dog #" + dogNumber); } } ///:~

7 Container disadvantage:unknown type import java.util.*; public class CatsAndDogs @SuppressWarnings("unchecked") { public static void main(String[] args) { ArrayList 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)).print(); // Dog is detected only at run-time } } ///:~

8 Generics and type-safe containers One of the problems of using pre-Java SE5 containers was that the compiler allowed you to insert an incorrect type into a container. With generics, you’re prevented, at compile time, from putting the wrong type of object into a container.

9 using Java generics import java.util.*; public class CatsAndDogs { public static void main(String[] args) { ArrayList cats = new ArrayList (); for(int i = 0; i < 7; i++) cats.add(new Cat(i)); // unable to add a dog to cats: !! cats.add(new Dog(7)); for(int i = 0; i < cats.size(); i++) cats.get(i).print(); // Dog is detected only at run-time } } ///:~

10 Making a type-consciousArrayList //: c11:MouseList.java // A type-conscious List. import java.util.*; 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(); } } ///:~templates ArrayList

11 Generics and type-safe containers import java.util.*; public class ApplesAndOrangesWithGenerics { public static void main(String[] args) { ArrayList apples = new ArrayList (); for(int i = 0; i < 3; i++) apples.add(new Apple()); // Compile-time error: // apples.add(new Orange()); for(int i = 0; i < apples.size(); i++) System.out.println(apples.get(i).id()); // Using foreach: for(Apple c : apples) System.out.println(c.id()); }

12 import java.util.*; public class PrintingContainers { 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 ())); } } ///:~toString equals hashCode [dog, dog, cat] [dog, cat] {dog=Spot, cat=Rags}

13 Iterators Iterators provide a unified way to put elements in or get elements out. 1.Ask a container to pass you an Iterator using a method called iterator( ). This Iterator will be ready to return the first element by next( ) method. 2.Get the next object in the sequence with next( ). 3.Chexk if there are any more objects in the sequence with hasNext( ). 4.Remove the last element returned by the iterator with remove( ).

14 //: c09:CatsAndDogs2.java // Simple container with Iterator. import java.util.*; public class CatsAndDogs2 { public static void main(String[] args) { ArrayList cats = new ArrayList (); for(int i = 0; i < 7; i++) cats.add(new Cat(i)); Iterator e = cats.iterator(); while(e.hasNext()) e.next().print(); } } ///:~

15 List functionality List (interface) –Order is the most important feature of a List; it promises to maintain elements in a particular sequence. –List adds a number of methods to Collection that allow insertion and removal of elements in the middle of a List. ArrayList –A List implemented with an array. –Allows rapid random access to elements –Slow when inserting and removing elements from the middle LinkedList –Provides optimal sequential access, with inexpensive insertions and deletions from the middle of the List. –Relatively slow for random access. (Use ArrayList instead.) –Additional methods: addFirst( ), addLast( ), getFirst( ), getLast( ), removeFirst( ), and removeLast( )

16 Making a stack from a LinkedList import java.util.*; public class StackL { private LinkedList list = new LinkedList (); public void push( T 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( new Integer(i) ); System.out.println(stack.top()); System.out.println(stack.top()); System.out.println(stack.pop()); } } ///:~

17 Set functionality HashSet, TreeSet and LinkedHashSet Set has exactly the same interface as Collection, so there isn’t any extra functionality like Lists, the Set is exactly a Collection. It just has different behavior. A Set refuses to hold more than one instance of each object value. (so we need implement equals() method) When creating your own types, you must define: –TreeSet: equals() method, implement the Comparable interface and define the compareTo( ) method. –HashSet: equals() method, hashCode() method

18 Map functionality Different types of Maps in JDK: HashMap, TreeMap, LinkedHashMap, WeakHashMap, and IdentityHashMap. Hashing is the most commonly used way to store elements in a map. When creating your own types for keys, you must define: –TreeMap: equals() method, implement the Comparable interface and define the compareTo( ) method. –HashMap: equals() method, hashCode() method The put(Object key, Object value) method adds a key- value pair into a container. get(Object key) gets the value corresponding to the given key. You can also test a Map to see if it contains a key or a value with containsKey( ) and containsValue( ).

19 Map functionality import java.util.*; class Counter { int i = 1; public String toString() { return Integer.toString(i); } } public class Statistics { public static void main(String[] args) { HashMap hm = new HashMap (); for(int i = 0; i < 10000; i++) { // Produce a number between 0 and 20: Integer r = new Integer((int)(Math.random() * 20)); if(hm.containsKey(r)) hm.get(r).i++; else hm.put(r, new Counter()); } System.out.println(hm); } } ///:~

20 Map functionality When a HashMap object is printed, the HashMap toString( ) method moves through all the key-value pairs and calls the toString( ) for each one. {15=529, 4=488, 19=518, 8=487, 11=501, 16=487, 18=507, 3=524, 7=474, 12=485, 17=493, 2=490, 13=540, 9=453, 6=512, 1=466, 14=522, 10=471, 5=522, 0=531}

21 Map functionality You might wonder at the necessity of the class Counter, Why not use int or Integer? Well, you can’t use an int because all of the containers can hold only Object references. –After you’ve seen containers, the wrapper classes might begin to make a little more sense to you, since you can’t put any of the primitive types in containers. However, Java wrappers(Integer) is constant objects. That is, there’s no way to change a value once a wrapper object has been created.

22 Hashing and hash codes In Statistics.java, a standard library class (Integer) was used as a key for the HashMap. It worked because it has all the necessary wiring to make it behave correctly as a key. But a common pitfall occurs with HashMaps when you create your own classes to be used as keys.

23 Map functionality import java.util.*; class MyKey { private int id; public MyKey(int i) { id=i; } public String toString() { return “ ID ” +Integer.toString(id); } } class Counter { int i = 1; public String toString() { return Integer.toString(i); } } public class Statistics1 { public static void main(String[] args) { HashMap hm = new HashMap (); for(int i = 0; i < 100; i++) { // Produce a number between 0 and 20: MyKey r = new MyKey ((int)(Math.random() * 20)); if(hm.containsKey(r)) hm.get(r).i++; else hm.put(r, new Counter()); } System.out.println(hm); } } ///:~

24 C:\Java\jdk1.5.0>bin\java Statistics1 {ID19=1, ID12=1, ID18=1, ID2=1, ID4=1, ID13=1, ID3=1, ID10=1, ID3=1, ID11=1, ID3=1, ID1=1, ID14=1, ID19=1, ID10=1, ID16=1, ID2=1, ID17=1, ID11=1, ID7=1, ID12=1, ID2=1, ID10=1, ID10=1, ID8=1, ID13=1, ID2=1, ID0=1, ID0=1, ID16=1, ID13=1, ID5=1, ID0=1, ID6=1, ID7=1, ID9=1, ID10=1, ID11=1, ID12=1, ID13=1, ID12=1, ID5=1, ID11=1, ID7=1, ID4=1, ID15=1, ID13=1, ID0=1, ID3=1, ID5=1, ID6=1, ID14=1, ID4=1, ID9=1, ID6=1, ID18=1, ID13=1, ID16=1, ID17=1, ID15=1, ID14=1, ID7=1, ID4=1, ID12=1, ID0=1, ID5=1, ID17=1, ID10=1, ID5=1, ID14=1, ID4=1, ID0=1, ID14=1, ID12=1, ID13=1, ID0=1, ID3=1, ID4=1, ID1=1, ID9=1, ID0=1, ID2=1, ID0=1, ID16=1, ID2=1, ID0=1, ID2=1, ID5=1, ID4=1, ID3=1, ID7=1, ID9=1, ID10=1, ID2=1, ID14=1, ID18=1, ID16=1, ID8=1, ID6=1, ID16=1} The problem is that MyKey is inherited from the common root class Object. It is Object’s hashCode( ) method that is used, and by default it just uses the address of its object. Thus, the first instance of MyKey (3) does not produce a hash code equal to the hash code for the second instance of MyKey (3) that we tried to use as a lookup.

25 You not only need to override hashCode( ), but also need to override the equals( ). equals( ) is used by the HashMap when trying to determine if your key is equal to any of the keys in the table. A proper equals( ) must satisfy the following five conditions: –Reflexive: For any x, x.equals(x) should return true. –Symmetric: For any x and y, x.equals(y) should return true if and only if y.equals(x) returns true. –Transitive: For any x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true. –Consistent: For any x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the object is modified. –For any non-null x, x.equals(null) should return false. When creating your own types, you must ensure that: If a.equals(b) then a.hashCode() =b.hashCode()

26 import java.util.*; class MyKey { private int id; public MyKey(int i) { id=i; } public String toString() { return “ ID ” +Integer.toString(id); } public int hashCode() { return id; } public boolean equals(Object o) { return (o instanceof MyKey) && (id ==((MyKey)o).id); } class Counter { int i = 1; public String toString() { return Integer.toString(i); } }

27 public class Statistics1 { public static void main(String[] args) { HashMap hm = new HashMap (); for(int i = 0; i < 100; i++) { // Produce a number between 0 and 20: MyKey r = new MyKey ((int)(Math.random() * 20)); if(hm.containsKey(r)) hm.get(r).i++; else hm.put(r, new Counter()); } System.out.println(hm); } } ///:~ C:\Java\jdk1.5.0>bin\java Statistics2 {ID15=5, ID4=4, ID19=7, ID8=3, ID11=11, ID16=9, ID18=7, ID3=3, ID7=4, ID12=5, ID17=1, ID2=5, ID13=5, ID9=9, ID6=4, ID1=4, ID14=3, ID10=5, ID5=2, ID0=4}

28 Exercises 1.Modify the example class StackL(ppt page15) to eliminate generics so that the stack can hold different wrapping class data(String, Integer, Double etc.) and the value we push or pop is printed to the scrren, and when we try to pop from an empty stack, an error message is shown. 2.Modify the example Statistics.java to count the number of character from ‘ A ’ to ‘ Z ’ of the string inputted as command argument. (use s.charAt(i) to get separate character)


Download ppt "11: Holding Your Objects Introduction to containers Container disadvantage: unknown type Iterators Container taxonomy Collection functionality List functionality."

Similar presentations


Ads by Google