Homework is important practice for you, but it’s not graded so you don’t
have to submit it.
This particular homework has you test and refactor a “bad” implementation of
List interface; you’ll also get to reflect a bit.
On Piazza you’ll find the
List interface we developed in
lecture as well as a “bad” implementation called
Before you do anything else, you should develop a set of JUnit 4 test drivers
Put all the general test cases for the
List interface into an abstract
ListTestBase.java; any specific test cases for
go into a concrete class
LinkedListTest.java which inherits from
ListTestBase as usual.
(Eventually you’ll want a
SentinelListTest.java as well of course, see
Be sure to test all methods and be sure to test all exceptions for
error situations as well.
Ideally you will make a complete set of tests before you start working on
LinkedListclass is “bad” in the sense that the code is really messy. Despite that, we believe it to be a correct implementation of the
LinkedList class follows the basic pattern for linked lists we’ve used
from the beginning of the course:
nullwhen there’s nothing in the list, otherwise they refer to the actual first node and the actual last node (which could be one and the same if the list has only one node).
nullfor the first node in the list, the next reference is
nullfor the last node in the list. (And if there’s only one node, of course both are
The result of this organization is that our code for modifying the list has to
constantly check whether this, that, or the other thing is
null and react
The code is full of conditionals where we do one thing for a
and another thing for a non-
In other words it’s horrible.
The idea for
SentinelList is to change all that, to remove (almost) all the
case distinctions around
To do that we start from a simple premise, however that premise does take some
getting used to:
SentinelListclass never gets to see them!
null. That is, even an empty list (as far as the interface is concerned) will have two nodes (as far as the implementation is concerned).
Listinterface considers to be “the list” at any point in time.
Let this sink in for a little while, then draw some examples, starting with the
As you’ll see, every insertion operation will now happen between two nodes,
and there’s no longer any need to deal with
That’s where the big simplification comes from!
Note that if you don’t actually sit down and try this out with a piece of paper
(or a whiteboard) you’ll never get it.
We’re not kidding, Peter has literally stacks of pages with scribbled little
list diagrams sketching the “before” and “after” situations for the various
That’s what you want to have too before you hack the code!
SentinelList.java and start refactoring!
Your primary goal is to replace the existing “
null marks the ends”
representation used by
LinkedList with one that uses sentinel nodes
Your secondary goal is to make the code as simple and concise as you possibly can. This will require that you find patterns in the existing code (primarily around insertion and removal) that can be “unified” into private helper methods; ideally the “many” public methods will mostly be reduced to one-liners that call the “few” private helpers. Note that the best patterns will only emerge after you have sentinels in.
Pay extra attention to avoiding duplicated code! (You want DRY and not WET code!) Here are a few examples of what we mean by that:
removeXmethods should be very short indeed and rely on only a few private methods that do the actual work; those private methods should have close to zero (that is 0) case distinctions involving
nullreferences in them.
The goal is to end up with a
List implementation that’s both simpler and
more concise than what we gave you to start with.
SentinelListalso make a copy of
SentinelListTestand start by compiling and running all of that. Then make your first few changes, compile again, test again. Then make the next few changes, compile again, test again. And so on, and so forth.
LinkedListclass we give you and for the
SentinelListclass you’re supposed to write.
LinkedList! No, you cannot use a
SentinelListhas to stand on its own, relying only on the interfaces provided!
This is not a programming problem; it’s a thinking and writing
(It’s practice for the kind of thing you’re likely to face in an interview.)
Write a reflection on the design we’ve come up with:
List interface itself and the
Position interface clients use to “talk
about” places in the data structure without “knowing” what those places really
Here are some things you could write about, although there are probably a lot
List, for example implementations using arrays of some sort instead of a bunch of
Nodeobjects. Can this actually be done using the existing interfaces? What kind of issues do you see?
Listinterface, but it’s rather different from ours. What are those differences and how can you explain them? (That is, assuming the Java designers are smart, capable people, why did they come up with such a different design? Why do they use integer positions for instance? Why do we not use those?)
Listinterface minimal in the sense that there are no operations we could leave out while still expressing what a list is? Which ones could we leave out and why? How would that impact the overall interface design? Are there operations we could leave out but shouldn’t, for example because they add a nice “symmetry”?
Feel free to take your reflection in any direction you think is useful, the
points above are simply suggestions.
We certainly won’t “get mad” if you tell us that our
List interface is really
bad, just as long as your reasoning is sound.
You want to convince us that you can think and write coherently about
programming independently of actually doing it!
At minimum, you should have the file
SentinelList.java containing your shiny
new list implementation of pure awesomeness as well as the necessary files for
your test cases (all three of those).
And of course all the various supporting classes and interfaces needed to
Everything should compile without warnings with the
-Xlint:all flag; there
should be no
checkstyle warnings either with the 601.226 configuration file
posted on Piazza.
Your reflection should be in your