Chapter 12 : Lists - PowerPoint PPT Presentation

About This Presentation
Title:

Chapter 12 : Lists

Description:

... SPADE,2)); if (hand.get(0).suit() == PlayingCard.SPADE) ... roll.add(new PlayingCard(PlayingCard.SPADE,2)); (Cannot add a PlayingCard to a StudentList. ... – PowerPoint PPT presentation

Number of Views:17
Avg rating:3.0/5.0
Slides: 90
Provided by: Emp115
Learn more at: https://www.cs.uno.edu
Category:
Tags: chapter | lists | spade

less

Transcript and Presenter's Notes

Title: Chapter 12 : Lists


1
Chapter 12 Lists
2
Objectives
  • After studying this chapter you should understand
  • the notion of container and its features
  • the specification of a list as a container
  • iteration as the control mechanism to process
    list entries
  • the notion of equality, and the pitfalls in
    overriding the method equals.
  • Also, you should be able to
  • use the class DefaultListltElementgt to create and
    manipulate list instances
  • implement iterative algorithms that manipulate
    lists.

3
Objectives
  • Also, you should be able to
  • use the class DefaultListltElementgt to create and
    manipulate list instances
  • implement iterative algorithms that manipulate
    lists.

4
Containers for collections of objects
  • Basic container operations include
  • adding an item
  • removing an item
  • determining if a particular item is in container
  • performing an operation on each item in the
    container.
  • Fundamental container characteristic
  • Container is a homogeneous collection

5
List as container
  • Finite container. It may be empty.
  • Its a sequence.
  • Its homogeneous. All the elements are of the
    same type.
  • It can contain multiple instances of same item.

6
Designing List StudentList
  • public void add (Student student)
  • Add the specified Student to the end of this
    list.
  • public void remove (Student student)
  • Remove the first occurrence of the specified
    Student from this list. Has no effect if the
    Student is not on this list.
  • public boolean contains (Student student)
  • This list contains the specified Student.
  • public int size ()
  • Number of elements in this list.
  • public Student get (int index)
  • The Student with the specified index.
  • require 0 lt index index lt this.size()
  • public void set (int index, Student student)
  • Replace the element at the specified position
    with the specified Student.
  • require 0 lt index index lt this.size()

7
Client of StudentList
  • StudentList roll new StudentList()
  • roll.add(new Student("Bill",)) // adding items
    to roll
  • if (roll.size() lt 10) //querying its size
  • Student s roll.get(3) // accessing a
    Student, where roll.size()gt3
  • // if finalGrade() is a Student method, we can
    write
  • if (roll.get(0).finalGrade() gt 70)

8
Specifying Lists
  • To model a list of PlayingCards.
  • a class has the same features as StudentList.
  • methods are modified to reflect that list
    elements are now instances of PlayingCard

9
Client safety
  • We can safely write code like

StudentList roll new StudentList() roll.add(new
Student("Bill",)) if (roll.get(0).finalGrade()
gt 70)
PlayingCardList hand new PlayingCardList() hand
.add(new PlayingCard(PlayingCard.SPADE,2)) if
(hand.get(0).suit() PlayingCard.SPADE)
10
Client safety
  • We expect the following to produce compiler
    errors
  • roll.add(new PlayingCard(PlayingCard.SPADE,2))
  • (Cannot add a PlayingCard to a StudentList.)
  • hand.get(0).finalGrade()
  • (hand.get(0) is a PlayingCard, no finalGrade
    method.)

11
at a cost Do not repeat yourself!
  • Implementation of classes StudentList, and
    PlayingCardList, will be virtually identical.
  • Client methods that manipulate StudentList
  • public void swap (StudentList list, int i, int j)
  • public void sort (StudentList list)
  • public int search (Student s, StudentList list)
  • Will need to be duplicated to deal with any other
    XXXList type!

12
Using abstraction to capture list-ness
  • AbstractList specifies and implements all list
    methods, subclasses will inherit the
    implementations.
  • Items in AbstractList are specified of type Object

public void add (Object object) Add the specified
Object to this list. public Object get (int
index) The Object on this list with the specified
index.
13
Subclassing AbstractList
  • In subclass StudentList we re-implement the
    methods dealing with Student instances

public Student get (int i) return
(Student)super.get(i) public void add (Object
student) assert student instanceof
Student super.add(student)
14
Subclassing AbstractList breaks LSP
  • Specification of add in AbstractList is

public void add (Object object) Add the specified
Object to this list.
  • While in StudentList is

15
Subclassing AbstractList breaks LSP
  • StudentList cannot be used where AbstractList is
    required.
  • Broken code

public void addAnObject (AbstractList list)
list.add(new Object())
16
Using generics to capture list-ness
  • Share specification and implementation
  • class definition specifies dummy Element type as
    parameter
  • Element is used in List implementation

public class ListltElementgt public void
add (Element element) public Element get
(int index)
17
Using generics to capture list-ness
  • List clients provide item type at creation to
    fill for Element

ListltStudentgt roll new ListltStudentgt() Listlt
PlayingCardgt hand new ListltPlayingCardgt()
18
List definition structure
19
public interface ListltElementgt A finite list of
Elements
Queries public int size () Number of elements in
this List. ensure this.size() gt 0 public
boolean isEmpty () This List contains no
elements. this.isEmpty() (this.size()
0) public Element get (int index) The Element
with the specified index. require 0 lt index
index lt this.size()
20
Queries (Cont.)
public boolean contains (Element element) This
List contains the specified Element. this.contain
s(element) (this.indexOf(element) gt
0) public int indexOf (Element element) The
index of the first occurrence of the specified
element, or -1 if this List does not contain the
specified element. ensure if this.indexOf(elemen
t) gt 0 this.get(this.indexOf(element)).equ
als (element) for all j 0 lt j j lt
this.indexOf(element) implies
!this.get(j).equals(element) if
this.indexOf(element) -1 for all indexes
j, !this.get(j).equals(element)
21
Commands
public void add (Element element) Append the
specified Element to the end of this List.
Equivalent to this.add(this.size(),element). requ
ire element ! null ensure this.size()
old.size() 1 this.get(this.size()-1)
element public void add (int index, Element
element) Insert the specified Element at the
specified index. require element !
null 0 lt index index lt this.size() ensure
this.size() old.size()
1 this.get(index) element for all j index
lt j j lt old.size() implies old.get(j)
this.get(j1)
22
Commands (Cont.)
public void remove (Element element) Remove the
first occurrence of the specified Element from
this List. Has no effect if the Element is not
contained in this List. public void remove (int
index) Remove the element with the specified
index. require 0 lt index index lt
this.size() ensure this.size() old.size()
- 1 for all j index lt j j lt
this.size() implies this.get(j)
old.get(j1) public void set (int index, Element
element) Replace the element at the specified
position with the specified Element. require
element ! null, 0 lt index index lt
this.size() public ListltElementgt copy () A copy
of this List. ensure this.copy() ! this,
this.copy().size() this.size() for
all indexes j, this.get(j).equals(this.copy().get(
j))
23
List iteration
  • To perform an operation for each element of
    container.

while ( condition ) statement
24
Loop structure to process all list elements
int i // index of next element to
process i 0 // starts with first list
element while ( i lt list.size() ) process
list.get(i) i i 1
25
Iterating to compute final average
public double finalAverage (ListltStudentgt
students) int i // index of students int
length // number of Students on the list int
sum // sum of grades up to, but not
including, // the i-th Student sum
0 length students.size() i 0 while (i
lt length) sum sum students.get(i).finalExa
m() i i1 return (double)sum /
(double)length
26
Execution of finalAverage() method
  • Assume we have the following student list data

list.get(0).finalExam() 75 list.get(1).finalExa
m() 80 list.get(2).finalExam()
93 list.get(3).finalExam() 67
  • Note that
  • list.size() 4
  • And list indices are 0, 1, 2, and 3

27
Execution of finalAverage() method
Loop initialization variables yield
Loop condition (i lt length ) is true Loop body
executes sum sum list.get(0).finalGrade()
28
Execution of finalAverage() method
And then executes i i 1
29
Execution of finalAverage() method
Loop condition (i lt length ) is true Loop body
executes sum sum list.get(1).finalGrade()
30
Execution of finalAverage() method
And then it executes i i 1
31
Execution of finalAverage() method
Loop condition (i lt length ) is true Loop body
executes sum sum list.get(2).finalGrade()
32
Execution of finalAverage() method
And then it executes i i 1
33
Execution of finalAverage() method
Loop condition (i lt length ) is true Loop body
executes sum sum list.get(3).finalGrade()
34
Execution of finalAverage() method
And then it executes i i 1
35
Execution of finalAverage() method
Loop condition (i lt length ) is now false, Loop
terminates. Method proceeds to compute division
and return value.
36
Finding the minimum grade
public int minFinalExam (ListltStudentgt
students) The lowest final exam grades of the
specified Students. require students.size() gt 0
  • Check final exam grade of each Student, maintain
    lowest seen.

int i // index of the next Student to see int
low // lowest final exam grade of Students //
seen so far
37
Finding the minimum grade
  • Need two variables

int i // index of the next Student to see int
low // lowest final exam grade of Students //
seen so far
  • To what values to initialize them?
  • Initialize i to 0 implies that no student has
    been seen,
  • So, what value to initialize low ?

38
Finding the minimum grade
  • Simplest solution Since list is not empty

low students.get(0).finalExam() i 1 //
this will be the next student to see.
  • Loop loop checks and updates low if needed

while (i lt students.size()) if
(students.get(i).finalExam() lt low) low
students.get(i).finalExam() i i1 return
low
39
Searching the list
  • Implement indexOf using the other List methods.

public int indexOf (Element element) The index of
the first occurrence of the specified element,
or -1 if this List does not contain the
specified element.
  • Use equals to compare list item to element

this.get(i).equals(element)
40
Searching the list
  • In search, iteration must stop as soon element
    is found in list.
  • Search is on as long as item examined is not
    equal to element.
  • If element not in list, make sure index does not
    go past size of list.

int i 0 // index of next element to
examine while ( i lt this.size()
!this.get(i).equals(element))
  • Note about conditional expression
  • order of operands
  • Expressions evaluated

41
Searching the list Loop invariant
  • i index of next element in list to examine.
  • This is always true during execution
  • No list item with index less than i is equal to
    element

42
Searching the list
  • What about body of loop?
  • Entering body of loop implies that current item
    is not equal to element, thus try next index.

int i 0 // index of the next element to
examine while (i lt this.size()
!this.get(i).equals(element)) i i 1
body of loop
43
Searching the list
  • The loop terminates when

i this.size() //thus item not in list
  • Or when

this.get(i).equals(element) //thus, item found
  • Either condition may be true after loop
    terminates.
  • Must check for them to return appropriate value.

44
Searching the list
public int indexOf (Element element) int i
0 // index of next element to examine while
(i lt this.size() !this.get(i).equals(eleme
nt)) i i1 if (i lt this.size()) return
i else return -1
45
Nested loops Removing repeated list items.
  • Problem Remove repeated entries from a list of
    Integer values.
  • Assume list is in variable elements.

private removeDuplicates () Remove duplicates
from the elements list
46
Nested loops Removing repeated list items
  • Design
  • For each list item, iterate through list removing
    all repetitions.
  • Loop invariant
  • No element with index less than i appears more
    than once

47
Nested loops Removing duplicate list items
48
Nested loops Removing duplicate list items
  • Need loop to remove entries in list equals to
    list.get(i)
  • can be written directly as a nested loop.
  • can write a private method.
  • Prefer to write a method to nest loops
  • Easier to write, read and understand.
  • Easier to test.

private void removeDuplicates () int i
0 while (i lt elements.size())
removeDuplicatesOfItemAt(i) i i 1
49
Removing duplicate list items
private void removeDuplicatesOfItemAt (int i)
int j // index of element to
check Integer item // remove duplicates of
this item elements.get(i) j i1 while (j
lt elements.size()) if (item.equals(elements.ge
t(j))) elements.remove(j) else j
j1
50
Nested loops Removing duplicate list items
  • Replacing invocation of removeDuplicatesOfItemAt
    with its body in removeDuplicates, resulting
    structure shows one while loop inside body of
    another loop nested loops

i 0 while (i lt elements.size()) Integer
item elements.get(i) int j i1 while (j lt
elements.size()) if (item.equals(elements.get(j)
)) elements.remove(j) else j j1 i
i1
51
Loop structure summary
initialization while (condition)
body conclusion
  • Initialization statements initialize variables
    used in the condition and in the body of the
    loop. Critical part of setting up loop.
  • Condition determines if body of the loop is to be
    executed.
  • Loop body defines one step in the solution
    processmust make sure that loop condition will
    ultimately become false, and loop terminates.
  • Concluding statements are not always necessary.

52
The for statement
for (initializationStatement condition
updateStatement) bodyStatement
  • While equivalent

initializationStatement while (condition)
bodyStatement updateStatement
53
The for statement
  • A for-loop iteration processing each element of a
    list

int i for (i 0 i lt list.size() i
i1) process list.get(i)
54
for statement example
  • Method average written with a for-loop

for (i 0 i lt length i i1) if
(students.get(i).finalExam() gt 0) sum
sum students.get(i).finalExam() count
count1
55
What does equal mean
  • Operator
  • compares two values for equality.
  • Two reference values are equal when they
    reference the same object.

Student s1 Student s2 s1 s2 is true
only if s1 and s2 refer to exactly the same
object.
56
What does equal mean
  • In the following situation

Student s1 new (John Doe, 12456,
.) Student s2 s1 Student s3 new (John
Doe, 12456, ) s1 s2 //will return true,
while s1 s3 //will return false.
57
Object equals
  • Every class inherits method equals from Object.
  • In Object, equals is by default defined using

public boolean equals (Object obj) return this
obj
  • If equal is not overridden, s1.equals(s2) means
    s1 s2.
  • They must be the same object to return true.

58
When to override equals
  • Often need to check if two different instances
    are equal.
  • Using will yield false.
  • Must use appropriate implementation of equals
  • Consider overriding equals in classes whose
    instances are immutable.
  • Think carefully to override equals in mutable
    class
  • in this case use only class attributes which are
    immutable.

59
Overriding equals pitfalls
  • Given the specification of the equals method

public boolean equals (Object obj)
  • Cannot redefine parameter, it will only overload
    it.
  • Overriding equals should be limited to top level
    class in an inheritance hierarchy.

60
Overriding equals
public class Circle extends ClosedFigure
public Circle (int radius) /
Two Circles are equal if and only if they have
the same radius. / public boolean equals
(Object obj) if (obj instanceof
Circle) return this.radius()
((Circle)obj).radius() else return
false
61
Overriding equals
public class ColoredCircle extends Circle
public ColoredCircle (int radius, Color c)
/ Two ColoredCircles are equal if
and only if they have the same radius and
Color. / public boolean equals (Object obj)
if (obj instanceof ColoredCircle) return
super.equals(obj) this.color().equals(
((ColoredCircle)obj).color()) else return
false
62
Problems with overriding
  • Broken subtyping by weakening the postcondition
    of Circles equals. The contract offered by
    Circle says

if c is a Circle, this.equals(c)
(this.radius() c.radius()).
  • ColoredCircle, however, promises only that

if c is a ColoredCircle, if this.equals(c), then
this.radius() c.radius().
63
Problems with overriding
  • A Circle client can see unequal Circles with same
    radius
  • if two Circles happen to be ColoredCircles of
    different colors, they test as unequal even if
    the client is viewing them as Circles and not
    ColoredCircles.

64
Problems with overriding
  • The following method

public void report (Circle c1, Circle c2) if
(c1.radius() c2.radius())
System.out.println("Circles are equal.") if
(!c1.equals(c2)) System.out.println("Circles
are not equal.")
  • Report that arguments are both equal and not
    equal if invoked as
  • report(new ColoredCircle(1,Color.BLUE), new
    ColoredCircle(1,Color.RED))

65
Equals properties are not met
  • equals conditions
  • reflexive x.equals(x) is true
  • symmetric if x.equals(y) is true, then so is
    y.equals(x).
  • transitive x.equals(y) and y.equals(z) then
    x.equals(z).
  • Circle c1 new Circle(1)
  • Circle c2 new ColoredCircle(1,Color.BLUE)
  • c1.equals(c2) is true, but c2.equals(c1) is
    false. ?
  • c1.equals(c2) compares them as Circle instances,
    while c2.equals(c1) compares them as
    ColoredCircle instances.

66
Equals properties are not met
Circle c1 new Circle(1) Circle c2 new
ColoredCircle(1,Color.BLUE)
  • c1.equals(c2) is true, but c2.equals(c1) is
    false. ?
  • c1.equals(c2) compares them as Circle instances,
    while c2.equals(c1) compares them as
    ColoredCircle instances.

67
A broken fix
public boolean equals (Object obj) if (obj
instanceof ColoredCircle) return
super.equals(obj) this.color().equals(
((ColoredCircle)obj).color()) else if (obj
instanceof Circle) return super.equals(obj)
else return false
68
A broken fix
  • Now if the argument is a Circle, but not a
    ColoredCircle, the two objects will be compared
    as Circles.

Circle c1 new Circle(1) Circle c2 new
ColoredCircle(1, Color.BLUE) both c1.equals(c2)
and c2.equals(c1) return true.
69
A broken fix
report(new ColoredCircle(1, Color.BLUE)), new
ColoredCircle(1, Color.RED))
  • Still reports that arguments are both equal and
    not equal.

70
A broken fix
  • equals is not transitive

Circle c1 new ColoredCircle(1,
Color.BLUE) Circle c2 new Circle(1) Circle c3
new ColoredCircle(1, Color.RED)
  • Then
  • c1.equals(c2) and c2.equals(c3) are both true,
  • but c1.equals(c3) is false.

71
Other attempts to fix equals
  • Use the getClass() method, that returns the
    run-time type of instances.
  • Define equals only if both arguments are of same
    run-time
  • i. equals properties become true.
  • ii. But subtyping is still broken. Two colored
    circles seen as Circle may be equal but unequal
    under ColoredCircle.

72
Another attempt to fix equals
  • Instead of subclassing use composition thus we
    do not have to override.

73
Simplest solution
  • Override equals only ONCE in a class hierarchy.
  • Programmers override equals and make the method
    final, so that subclasses cannot override it.

74
Implementing List AbstractList
  • Use an abstract class as a basis for constructing
    list implementations.
  • The abstract class defines a number of list
    methods in terms of a few basic methods.
  • A concrete class, need only implement these.

75
Methods implemented in AbstractList
public boolean isEmpty () return this.size()
0 public boolean contains (Element
element) return this.indexOf(element) !
-1 public void add (Element element)
this.add(this.size(),element) public void
set (int i, Element element) this.remove(i) t
his.add(i, element) public void remove
(Element element) int i this.indexOf(element)
if (i ! -1) this.remove(i)
76
Methods implemented in AbstractList
public int indexOf (Element element) int i
0 // index of the next element to
examine while (i lt this.size()
!this.get(i).equals(element)) i
i1 if (i lt this.size()) return
i else return -1
77
Methods implemented in AbstractList
  • We also provide an implementation of toString

public String toString () String s "" int
n this.size() if (n gt 0) s s
this.get(0).toString() int index 1 while
(index lt n) s s ", "
this.get(index).toString() index
index1 s s "" return s
78
Method to be implemented in subclasses
  • This leaves only five methods undefined

public int size() public void get (int
index) public void add (int index, Element
element) public void remove (int index) public
ListltElementgt copy ()
79
Implementing DefaultList
  • java.util.VectorltElementgt provides functionality
    required.
  • A Vector is a list-like container in which
    elements are accessed by index.
  • But Vector interface is not the desired one.
  • We adapt or wrap the existing class.
  • Thus implementation of DefaultList will have a
    Vector component

80
Static diagram for DefaultList
interface
ListltElementgt
adaptee
81
DefaultList implementation
public class DefaultListltElementgt extends
AbstractListltElementgt private
java.util.VectorltElementgt elements public
DefaultList () this.elements new
java.util.vectorltElementgt() public int size
() return this.elements.size() public
Element get (int index) return
this.elements.get(index)
82
DefaultList implementation
public void add (int index, Element element)
this.elements.add(index,element) public
void remove (int index) this.elements.removeEle
mentAt(index) public void set (int index,
Element element) this.elements.setElementAt(ele
ment,index)
83
Summary
  • examined specification and application of a
    simple container called a list.
  • A list is a finite sequence of objects, all of
    the same type.
  • An individual element on the list can be accessed
    by an integer index, denoting how far the element
    is from the front of the list.
  • List classes are characterized by the kind of
    items they can contain. Thus one class models a
    list of Students, while another class models a
    list of PlayingCards. The specifications and
    implementations of these different lists classes
    are almost identical. To avoid having to repeat
    the same code over and over for each different
    list class, Java provides a generic facility.
    This allows us to define interfaces, classes, and
    methods with type parameters. Thus we define
    the interface ListltElementgt where Element is a
    type parameter. We instantiate the generic by
    providing an actual type argument
    ListltStudentgt is a list of Students, ListltStringgt
    a list of Strings, and so on.

84
Summary
  • List classes are characterized by the kind of
    items they can contain.
  • one class models a list of Students,
  • while another class models a list of
    PlayingCards.
  • Specifications and implementations of these
    different lists classes are almost identical.
  • To avoid having to repeat same code over and over
    for each different list class, Java provides a
    generic facility.

85
Summary
  • Javas generic facility allows to define
    interfaces, classes, and methods with type
    parameters.
  • Define interface ListltElementgt where Element is a
    type parameter.
  • instantiate the generic by providing an actual
    type argument
  • ListltStudentgt is a list of Students,
  • ListltStringgt a list of Strings, and so on.

86
Summary
  • Often want to perform some operation on each
    element in a container.
  • Standard pattern is to use a while loop and index
    to iterate through the list

int i i 0 while (i lt list.size()) process
list.get(i) i i 1
87
Summary
  • To search a container for an element must have an
    exact idea of what it means for two objects to be
    equal.
  • For mutable objects, equal generally means
    identical.
  • With immutable objects, it is often the case that
    several distinct object can represent the same
    thing.
  • two different Strings might contain the same
    sequence of characters,
  • two different Dates might denote the same actual
    date.
  • Might want to override the inherited method
    equals so that distinct objects that represent
    the same thing compare as equal.

88
Summary
  • Must be very careful overriding equals
  • Method equals should satisfy the reflexive,
    symmetric, and transitive properties.
  • It is difficult to satisfy these properties if
    equals is overridden more than once in a chain of
    subclasses.

89
Summary
  • ListltElementgt is defined as a generic interface
    that captures the functionality of a sequential
    container.
  • Defined an abstract class AbstractListltElementgt
    that implements most of the functionality and
    provides a basis for developing complete concrete
    implementations.
  • DefaultListltElementgt, wraps the standard library
    class, java.util.VectorltElementgt.
Write a Comment
User Comments (0)
About PowerShow.com