Lecture 5: Implementing Lists, Version 1

Similar documents
Lecture 7: Implementing Lists, Version 2

Lecture 7: Lists, Version 2 (with Mutation)

Subclassing for ADTs Implementation

Homework 2: Imperative Due: 5:00 PM, Feb 15, 2019

Lecture 14: Exceptions 10:00 AM, Feb 26, 2018

Lecture 8: Iterators and More Mutation

Lecture 17: Implementing HashTables 10:00 AM, Mar 5, 2018

CS2102: Lecture on Abstract Classes and Inheritance. Kathi Fisler

Lecture 16: HashTables 10:00 AM, Mar 2, 2018

Object-Oriented Design Lecture 11 CS 3500 Spring 2010 (Pucella) Tuesday, Feb 16, 2010

Lab 4: Imperative & Debugging 12:00 PM, Feb 14, 2018

Object-Oriented Design Lecture 13 CSU 370 Fall 2008 (Pucella) Friday, Oct 31, 2008

Lab 5: Java IO 12:00 PM, Feb 21, 2018

CS 151. Linked Lists, Recursively Implemented. Wednesday, October 3, 12

Lecture 4: Inheritence and Abstract Classes

(Provisional) Lecture 08: List recursion and recursive diagrams 10:00 AM, Sep 22, 2017

Lab 2: Object-Oriented Design 12:00 PM, Jan 31, 2018

Object-Oriented Design Lecture 3 CSU 370 Fall 2007 (Pucella) Friday, Sep 14, 2007

Lab 7: OCaml 12:00 PM, Oct 22, 2017

Good Coding Practices Spring 2018

CS 61B Discussion 5: Inheritance II Fall 2014

Lecture 11: In-Place Sorting and Loop Invariants 10:00 AM, Feb 16, 2018

Lecture 21: The Many Hats of Scala: OOP 10:00 AM, Mar 14, 2018

Week 3 Classes and Objects

Homework 2: Imperative Due: 5:00 PM, Feb 16, 2018

16 Multiple Inheritance and Extending ADTs

Homework 8: Matrices Due: 11:59 PM, Oct 30, 2018

CSCI-1200 Data Structures Spring 2018 Lecture 14 Associative Containers (Maps), Part 1 (and Problem Solving Too)

Recursive Data and Recursive Functions

Inf1-OOP. OOP Exam Review. Perdita Stevens, adapting earlier version by Ewan Klein. March 16, School of Informatics

QUIZ. What is wrong with this code that uses default arguments?

Lecture 23: Priority Queues, Part 2 10:00 AM, Mar 19, 2018

CS152: Programming Languages. Lecture 7 Lambda Calculus. Dan Grossman Spring 2011

Homework 6: Higher-Order Procedures Due: 10:00 PM, Oct 17, 2017

CS 220: Introduction to Parallel Computing. Arrays. Lecture 4

Intro. Scheme Basics. scm> 5 5. scm>

6.005 Elements of Software Construction Fall 2008

(Provisional) Lecture 22: Rackette Overview, Binary Tree Analysis 10:00 AM, Oct 27, 2017

Lecture 12: Abstraction Functions

Lab 10: OCaml sequences, comparators, stable sorting 12:00 PM, Nov 12, 2017

Rescuing Lost Files from CDs and DVDs

Section 0.3 The Order of Operations

CS201 - Assignment 3, Part 2 Due: Wednesday March 5, at the beginning of class

Homework 4: Hash Tables Due: 5:00 PM, Mar 9, 2018

Homework 6: Higher-Order Procedures Due: 11:59 PM, Oct 16, 2018

Lecture 12: Dynamic Programming Part 1 10:00 AM, Feb 21, 2018

3 ADT Implementation in Java

Announcements. CS18000: Problem Solving And Object-Oriented Programming

Control Structures. Code can be purely arithmetic assignments. At some point we will need some kind of control or decision making process to occur

Matching & more list functions

Designing Robust Classes

Defining Your Own Classes

Lecture 22: Garbage Collection 10:00 AM, Mar 16, 2018

Text Input and Conditionals

Summer 2017 Discussion 10: July 25, Introduction. 2 Primitives and Define

Inf1-OP. Inf1-OP Exam Review. Timothy Hospedales, adapting earlier version by Perdita Stevens and Ewan Klein. March 20, School of Informatics

Administration. Exceptions. Leftovers. Agenda. When Things Go Wrong. Handling Errors. CS 99 Summer 2000 Michael Clarkson Lecture 11

These are notes for the third lecture; if statements and loops.

CS201 - Assignment 3, Part 1 Due: Friday February 28, at the beginning of class

The story so far. Elements of Programming Languages. Pairs in various languages. Pairs

Lab 10: Sockets 12:00 PM, Apr 4, 2018

Lecture 23: Priority Queues, Part 2 10:00 AM, Mar 19, 2018

CS1102: Macros and Recursion

Thinking Functionally

Code Reuse: Inheritance

CS/ENGRD 2110 SPRING Lecture 3: Fields, getters and setters, constructors, testing

CS1 Lecture 5 Jan. 25, 2019

Tips from the experts: How to waste a lot of time on this assignment

Scala Style Guide Spring 2018

QUIZ Friends class Y;

CS/ENGRD 2110 SPRING Lecture 7: Interfaces and Abstract Classes

CS211 Computers and Programming Matthew Harris and Alexa Sharp July 9, Boggle

Classes, interfaces, & documentation. Review of basic building blocks

BM214E Object Oriented Programming Lecture 8

Programming Languages and Techniques (CIS120)

Recursively Enumerable Languages, Turing Machines, and Decidability

Harvard School of Engineering and Applied Sciences CS 152: Programming Languages

BASIC COMPUTATION. public static void main(string [] args) Fundamentals of Computer Science I

Chapter 4 Defining Classes I

21 Abstracting Traversals

CS1102: What is a Programming Language?

CSE : Python Programming. Homework 5 and Projects. Announcements. Course project: Overview. Course Project: Grading criteria

Express Yourself. Writing Your Own Classes

Whereweare. CS-XXX: Graduate Programming Languages. Lecture 7 Lambda Calculus. Adding data structures. Data + Code. What about functions

COSC 2P91. Introduction Part Deux. Week 1b. Brock University. Brock University (Week 1b) Introduction Part Deux 1 / 14

Assertions and Exceptions Lecture 11 Fall 2005

Topic 7: Algebraic Data Types

OCaml Style Guide Fall 2017

Module 5: Lists. Readings: HtDP, Sections 9, 10.

Comp215: More lists. Dan S. Wallach (Rice University) Copyright 2015, Dan S. Wallach. All rights reserved.

Adding Machine Run 2

CS558 Programming Languages

The Design Recipe Fall 2017

17 Multiple Inheritance and ADT Extensions

CMSC131. Exceptions and Exception Handling. When things go "wrong" in a program, what should happen.

Due: 9 February 2017 at 1159pm (2359, Pacific Standard Time)

Homework 7: Subsets Due: 11:59 PM, Oct 23, 2018

Lecture 23: Priority Queues 10:00 AM, Mar 19, 2018

Binghamton University. CS-140 Fall Problem Solving. Creating a class from scratch

BM214E Object Oriented Programming Lecture 4

Transcription:

CS18 Integrated Introduction to Computer Science Fisler, Nelson Lecture 5: Implementing Lists, Version 1 Contents 1 Implementing Lists 1 2 Methods 2 2.1 isempty........................................... 2 2.2 addfirst........................................... 3 2.3 remeltonce......................................... 3 2.4 head and tail........................................ 3 2.5 size.............................................. 5 2.5.1 Adding Computation to Constructors...................... 5 3 Creating an Abstract Class 6 4 Printing Lists: tostring methods 6 Objectives By the end of this lecture, you will know: ˆ How to implement lists using classes By the end of this lecture, you will be able to: ˆ Use classes to implement recursively-defined data structures 1 Implementing Lists Now that we have covered the basics of OO, let s start applying OO to implement familiar data structures. Today, we start by implementing lists. We ll implement lists of numbers for now, for simplicity. In CS17, you saw a definition of lists along the lines of the following: A list-of-numbers is either * empty, or * (cons number list-of-numbers) Using this as a guide, we want to implement lists in Java.

Give it a try can you turn this definition into a collection of classes, interfaces, abstract classes, etc. Note: if you have had some Java before, use only features and constructs that we have covered in the course so far. Note the similarity between this and our previous setup of Boas and Dillos as Animals: there, we needed an interface for the shared type name, and a class for each variant. Following that, here s what you should have in Java (perhaps with different class/interface/variable names): public interface IList { public EmptyList() { int first; IList rest; public NodeList(int fst, IList rst) { this.first = fst; this.rest = rst; Side note for those with prior Java: Likely, many of you wanted to use null in your solution. Hold that thought. It actually isn t good OO practice, even though it is common practice in Java. We ll discuss the null-based solution explicitly next week (and explain what s wrong with it from an OO perspective). How could we create a list of three numbers with these classes? new NodeList(3, new NodeList(6, new NodeList(1, new EmptyList()))) With a class hierarchy and a sample of data in hand, we can turn to writing methods on our list class. 2 Methods Here s the IList interface that we want to implement in this lecture. (Note: I m intentionally not using javadoc to make the notes more compact the posted code uses Javadoc instead, as you should when writing programs for homework, etc) public interface IList { public boolean isempty(); public IList addfirst(int elt); public IList remeltonce(int elt); public int head(); public IList tail(); public int size(); // is the list empty? // add element to front of the list // remove first occurrence of elt // get the head of the list // get the tail of the list // the number of elements in the list 2

We ll work on these in order. 2.1 isempty This one is straightforward: each list class returns a boolean constant indicating whether or not it is empty. For example: public boolean isempty() { return true; 2.2 addfirst Here, we create a new NodeList with the given element as the first item and this as the rest of the list. public IList addfirst(int elt) { return new NodeList(elt, this); Note that this code is identical between the two list classes, so arguably you would make an abstract class to share this code. We skipped this in lecture so we could get through the other methods, but it is shown in the posted code. Now that we have addfirst, we can rewrite our example list as follows: new EmptyList().addFirst(1).addFirst(6).addFirst(3) Note that the elements appear to be written in the opposite order from our original example. You should convince yourself that these two expressions will produce lists with the same elements in the same order. 2.3 remeltonce In the EmptyList case, there s nothing to remove, so the method just returns this. In the NodeList case, we check whether the node contains the element, then either remove it or pass the computation on to the rest of the list to perform: public IList remeltonce(int remelt) { if (remelt == this.first) { 3

return this.rest; else { return new NodeList(this.first, this.rest.remeltonce(remelt)); Note that this is the same recursive solution that you would have written in CS17. We don t lose recursion as a technique just because we have switched to Java. 2.4 head and tail What if we want to get the head and tail (or first and rest) of the list? You might be tempted to do this by accessing the first and rest fields directly, as in the following example: public class ListTest { // is 2 the first element in the list? public boolean startswithtwo(ilist alist) { return (alist.first == 2); Stop and think: what do you expect will happen if you enter this code in Eclipse? Eclipse flags this code, reporting that it can t find the first field in alist (which has type IList). Should we change the parameter type to NodeList? That would make the error go away, but it is meaningful to ask whether an empty list starts with 2 (the answer would just be false). Rather than access fields directly (which isn t good programming practice anyway), we will introduce methods for getting the first and rest portions of the list. In NodeList, they look like: public int head() { return this.first; public IList tail() { return this.rest; What happens in EmptyList, however? There are no first or rest components to return, so what should happen? Both of these methods should raise errors, since it isn t meaningful to break down an empty list: public int head() { throw new RuntimeException("Attempt to take head of empty list"); 4

public IList tail() { throw new RuntimeException("Attempt to take tail of empty list"); In Java, RuntimeExceptions are for errors that you can t really recover from gracefully (like division by 0). They result in the program stopping completely. Later in the course, we will see more sophisticated situations of handling errors. Unlike the exception that you saw in lab, you don t need throws annotations for RuntimeExceptions. They are the closest Java analog to the simple error raising that you did in CS17. 2.5 size Finally, we turn to a method that returns the size of the list. You ve written recursive length functions many times in CS17, and we could certainly do the same here (following a pattern similar to that we used for remeltonce). But can we do that computation more efficiently? The size of the list doesn t change dynamically: it s a fixed value for any particular list, so it seems worth just storing it in a field and returning the field value whenever someone calls the size method. Specifically, we d like to do the following: int first; IList rest; int eltcount; public int size() { return this.eltcount; The interesting question here lies in the constructor: how should the constructor set up the value of eltcount? As a reminder, here is the constructor before we add the eltcount field: int first; IList rest; public NodeList(int fst, IList rst) { this.first = fst; this.rest = rst; Should we just add a parameter to the constructor that asks for the size? That would be inconvenient for the programmer who uses our list classes. For example, the list-example code we wrote before would now have to change to 5

new NodeList(3, new NodeList(6, new NodeList(1, new EmptyList(), 1), 2), 3) (where the 1), 2), 3 at the end of the line adds the sizes). Our definition of the addfirst method would also be affected. The eltcount field is our own implementation detail to make the size method more efficient, so it should not be visible to the user of our code. 2.5.1 Adding Computation to Constructors Constructors are just methods that are used to create objects. Like all methods, they can do arbitrary computation to complete their tasks. In this case, we want the constructor to compute the size when we create the list, then store that value in the field. Here s the code: int first; IList rest; int eltcount; public NodeList(int fst, IList rst) { this.first = fst; this.rest = rst; this.eltcount = 1 + rst.size(); For the empty list, we simply initialize the eltcount to 0. 3 Creating an Abstract Class With the addition of the eltcount, we now have another bit of code that is shared between the EmptyList and NodeList classes. This definitely points to an abstract class to share these details. Trying to write it for yourself is a terrific exercise: Try creating this abstract class (write it on paper) before looking at the posted code for today s lecture (which shows the solution) If you look at the posted code, you ll see that the implements IList annotation has also elevated to the abstract class. Since the interface is common to all classes that extend AbsList, it makes sense to annotate the abstract class instead. 4 Printing Lists: tostring methods One last tidbit, which is not about list classes in particular, but does show you a practical aspect of working in Java. Sometimes, we just want to print out the result of a computation withut going through a test case. For example, we might want to have the following code in the main method of our TestList class: 6

public class ListTest { public static void main(string[] args) { IList list1 = (new EmptyList()).addFirst(3).addFirst(6).addFirst(1); System.out.println(list1); If we do this, we see something like lec05.nodelist@15db9742 What is this? Remember our memory maps? This is saying that there s an object at memory address 15db9742 that was created from the NodeList class in the lec05 package. Not very useful, right? In Java, when you define classes, you also want to tell Java what to print out about objects in the class when needed. We do this by putting a method named tostring in the EmptyList and NodeList classes. @Override public String tostring() { return "empty"; @Override public String tostring() { return this.first + ", " + this.rest.tostring(); With these, our main method snippet now displays 1, 6, 3, empty You don t need to mention tostring in the interface: every Java class gets a default tostring method that you can override with a custom defintion, as we did here. The @Override annotation indicates that we are providing a refined definition of a method that otherwise already exists in the class. Nothing goes wrong if you leave it off, but it is good practice to include it. 7

Please let us know if you find any mistakes, inconsistencies, or confusing language in this or any other CS18 document by filling out the anonymous feedback form: http://cs.brown.edu/ courses/cs018/feedback. 8