CS2110: SW Development Methods OO Design and the Java Collections Framework (part 1) • Textbook readings: • MSD: parts of Chapter 9 • We’ll skip some of this now and come back to it later • Read these: • Page 611 through Section 9.3.3 • Pages 641-647 • More pages here soon… The Big Picture for this Unit • See how inheritance concepts are useful • Perhaps for you as you build classes • Definitely for Java class libraries that you use • Learn more about Java Collections Framework • ArrayList is part of this • Built on principles we just studied (inheritance, interfaces, etc.) • Learn how to make use of these reusable components, and the good OO principles behind their design • Along the way, learn more about class design Application Framework • What’s an OOP framework? • A large set of classes developed by someone else • Partially complete: we add to it to make a complete working program • MSD text: a unified architecture, works together, seamless, common interface • Examples: • GUI frameworks: Java Swing, Microsoft WinForms and MFC (for C++) • Others: Java Collections • Often: the “main” program control is built into the framework • Not ours to worry about! • We’ll see this for Swing later The Java Collections Framework • A common set of operations for “abstract” data structures • List interface: operations available on any kind of list • Set interface: operations available on any kind of set • A set of useful concrete classes that we can use • E.g. ArrayList, LinkedList, HashSet, TreeSet • A common set of operations for all Collections • Collection interface: operations we can do on any kind of Collection object • Collections class: contains static methods that can process Collection and List objects Reminder • You will want to use: • Concrete classes (e.g. ArrayList) • Collections operations (e.g. sort, shuffle, max) • References to interfaces when it makes sense • You are less likely to • Design a new Collection • But still, seeing how it’s been done will teach you good OO design principles Real Collection Interfaces in Java • All collections meet Collection interface: boolean add(E obj); Iterator iterator(); int size(); boolean isEmpty(); boolean contains(E obj); boolean containsAll (Collection other); … • See Java API documentation for all methods Collections and Abstract Classes • To define a new Collection, one must implement all methods -- a pain! • Better: define a skeletal implementation class • Leaves primitives undefined: add(), iterator() • Defines other methods in terms of those • Concrete collection class inherits from skeletal class • Defines “primitives” • Overrides any methods it chooses too • Java library: AbstractCollection • Implements Collection interface • You inherit from it to roll your own Collection Abstract Class Methods • Some collection methods can be defined “abstractly” • Method from abstract class below uses other methods like add(), iterator methods, etc. • All of those defined in concrete subclass public boolean addAll (Collection from) { Iterator iterFrom = from.iterator(); boolean modified = false; while ( iterFrom.hasNext() ) if ( add(iterFrom.next()) ) modified = true; return modified; } Who is most likely to use Abstract Collection? 1. You, a regular programming building applications 2. Someone developing new classes for a library for others to use List Interface in Java • Two concrete classes for lists: • ArrayList, LinkedList • Both implement the List interface • Which extends the Collection interface and adds: E get(int index); E set(int index, E element); E remove(int index); void add(int index, E element); int indexOf(Object o); int lastIndexOf(Object o); List<E> subList(int from, int to); … • See Java API documentation for all methods Set Interface in Java • Two concrete classes for sets: • HashSet, TreeSet • Both implement the Set interface • Which is actually the same as the Collection interface but some methods have more specific meaning. E.g.: boolean add(E element); // return false if duplicate • See p. 625 for methods that take a Collection as a parameter to do a contains/add/retain/remove • See Java API documentation for all methods • More on Sets later! Which are legal? 1. 2. 3. 4. 5. List<E> x = new ArrayList<E>(); List<E> x = new List<E> (); ArrayList<E> x = new List<E>(); Collection<E> x = new ArrayList<E>(); Set<E> x = new ArrayList<E>(); Inheritance and Design • Why would we do: List<E> x = new ArrayList<E>(); • One of three reasons we gave about why inheritance is used: Flexible design • We said (earlier): • Gives us more flexibility at run-time in calling operations on objects that might be of different types • Recall we use reference variables to “point to” objects • You know how polymorphism supports this • Now, two ideas about what makes a good design • Abstraction; Hiding Design Decisions Important Principle: Abstraction • Inheritance is an example of the principle of abstraction • http://en.wikipedia.org/wiki/Abstraction_%28computer_science%29 • Inheritance of implementation (IS-A) • You can think of a subclass item as a type of some more general type of object • Same state, some common behavior • Inheritance of interface (e.g. Java interfaces) • You can think of an object as an instance of something that can be used or operated on in a certain defined way • E.g. it’s comparable, printable, playable, drawable Hiding Design Decisions • The “black box” idea is important in design • Some “component” X, i.e. part of the system, is like a black box • The rest of the system knows how to interact with it through its interface (“interface” in general sense) • We swap in many different components for X as long as each has the same interface as X Hiding Design Decisions in OO • In OO software: • We reference components by type, I.e. an objectreference ref defined by: • Interface or Superclass (perhaps abstract superclass) • Examples: PlayableItem p; // abstract class TimePiece t; // interface public void syncTimeWith(TimePiece t) {…} ArrayList<PlayableItem> thePlayList; • What kind of object is the reference really pointing at? • The client-code doesn’t have to know. • But it does know what interface is supported. Hiding Design Decisions • A term for hiding design decisions this way is: information hiding • But information means more than data here • It means how things are designed or implemented • An object-reference to a Java interface or a superclass is a use of abstraction • Coding using abstractions makes systems more flexible, easy to change, easier to re-use parts • Could rephrase this as “coding to abstractions” • Result: better software design • (Seems vague? Too “abstract”? Don’t worry. You’ll see more later!) Iterators • “Iteration” means moving through a set of items • Most basic example: using a for or while loop with an array or ArrayList • We usually use an index variable i to access each item • Major point: • We can think of iteration at a higher level of abstraction… • where details of implementation are hidden • Have “something” that helps us get first item, next time, are there any left, etc. • Generally applies to any collection Iterator objects in Java • In OO languages like Java we use iterator objects to move through any Collection • Question: How do we get an iterator object? Answer: We get it from the Collection itself! • Question: What exactly does the Collection give us? Answer: We don’t really need to know! All we need to know is the Iterator interface this object implements. • Method in Collection: Iterator<E> iterator(); • Iterator is an interface, so we can use it as a type and then call methods on objects of that type Iterator Interface • Three fundamental methods: E next(); // where E is Collection’s element type boolean hasNext(); void remove(); • remove() is “optional” (not always defined). • removes the item we last passed over • can be called once per call to next() • the only safe way to remove an item while an iteration is taking place Example Iterator Code • Traverse a collection of Widgets named c and get each object, then remove it. Iterator<Widget> iter = c.iterator(); while ( iter.hasNext() ) { Widget w = iter.next(); // do something with w iter.remove(); } Generics and foreach • A simpler way (since Java 5.0) • A “foreach” statement simplifies that the previous idiom • Generics: • When you define a collection, you associate it with a particular type it will store • Think of every collection as having a “two-part type” • ArrayList<String> has type “ArrayList-of-Strings” • Also can define methods etc. using this bound-type Example: • Example of generic collections and foreach in use: List<Double> myList = new ArrayList<Double>(); for (Double item : myList ) { // “foreach” stmt System.out.println(“List myList contains ” + item); } • Advantages: • Concise, easy to understand • Disadvantage: no iterator, so cannot call iterator methods on an item as you visit each one • Can’t call iter.remove() ListIterator • Any type of Collection can have an Iterator • A List is a specialized form of Collection • A List collection can give you a ListIterator object that has a richer set of methods than a “plain” iterator • See pages 630-633 in MSD textbook • To get one, call the listIterator() method on a List • Can get one that starts at last item by calling: ListIterator<E> itr = lst.listIterator(lst.size()-1); • We’ll see you can move “backwards” through a List ListIterator Methods • Additional methods (beyond those in Iterator): boolean hasPrevious(); E previous(); int nextIndex(); // index from 0 to size()-1 int previousIndex(); void set(E o); void add(E o); void remove() // overrides the one in Iterator • These last three are based on the cursor! ListIterator and the “cursor” • Study pp. 631 in MSD textbook for details • Cursor “points to” a position between items • Or before the first item, or after the last item • Not the same as an item’s index! • remove() and set() • Affects the item just returned by next() or previous() • Can’t change an item without moving over it! • add() – adds an item in between two items • before the item just returned by next(), and • after the item just returned by previous() • All this is useful but tricky! Step Back for the Big Picture • Why learn and use Iterators and ListIterators? Why not just use a for-loop and index value with an ArrayList or array? • Practical reasons: • Iterators and ListIterators work with any Collection/List class (e.g. LinkedLists, sets, maps, trees, etc.) • If you change from one Collection to another, there is much less code to change • “Theoretical”: • This is an example of procedural abstraction Abstraction in CS • What’s the concept of abstraction again? • Wikipedia (general def.): An abstraction is an idea, conceptualization, or word for the collection of qualities that identify the referent of a word used to describe concrete objects or phenomena. • Wikipedia (CS): In computer science, abstraction is a mechanism and practice to reduce and factor out details so that one can focus on a few concepts at a time. • Allows us to group things that “are the same” • Process of abstraction vs. an abstraction (a thing) Procedural vs. Data Abstraction • Data Abstraction • An abstraction that hides details of how a data object is stored, represented, etc. • Procedural Abstraction • An abstraction that hides details associated with executing an operation or task • Sometimes people refer to Iteration Abstraction • Note that giving something a name is an important part of abstraction • I can refer to it. We understand it. We agree on it. You Already Understand Data Abstraction! • Example 1: Floating point numbers: • Details we care about: sign, whole-part, fractional part, operations • In a computer: • How large/small can the whole-part be? How many digits in the fraction? (IEEE 754 standard?) • In Java, we can represent NaN (“not a number”) double d = doSomeOperation(…); if ( Double.isNaN(d) ) … // invalid double returned! (Note use of static method defined in class Double) You Already Understand Data Abstraction! (2) • Example 2: Classes and Objects • What’s a string? A sequence of characters • Has a size. We concatenate them. Other operations. • But what is it “inside”? (Do we care?) • Example 3: Classes and Superclasses (and Interfaces) • Manager extends Employee extends Person • We can treat a set of people-objects using type Person, ignoring details about subclasses You Already Understand Procedural Abstraction! • Simple Methods, e.g. a sqrt() method • Hides the details of how it works • “Exposes” an interface we can use • We think of it and use it in terms of its purpose and interface • Loops and Iteration • We often think/design at a level higher than implementation • “I need a loop to do that.” (For-loop, while-loop? Does it matter?) • “I need to do this operation for each item.” • An iteration or repetition is implied. End of Part 1 on this topic. What’s Next? • Controlling execution with “function objects” • Comparator classes: passing an instance to sort() • Another example of procedural abstraction • Oh wait! We did this earlier! But let’s talk about this: Why are Comparator objects a good example of abstraction? Which kind? • Java collections for Sets and Maps