import java.util.ArrayList; /** * A class to maintain an arbitrarily long list of notes. * Notes are numbered for external reference by a human user. * In this version, note numbers start at 0. * * @author David J. Barnes and Michael Kolling. * @version 2008.03.30 */ public class Notebook { // Storage for an arbitrary number of notes. private ArrayList notes; /** * Perform any initialization that is required for the * notebook. */ public Notebook() { notes = new ArrayList(); // Creates empty ArrayList } /** * Store a new note into the notebook. * @param note The note to be stored. */ public void storeNote(String note) { notes.add(note); } /** * Store a new note into the notebook. * @param note The note to be stored. * @param position Position at which note should be stored */ public void storeNoteAtPosition(String note, int position) { notes.add(position, note); } /** * Returns the number of notes in the collection. * @return The number of notes currently in the notebook. */ public int numberOfNotes() { return notes.size(); } /** * Show a note. * @param noteNumber The number of the note to be shown. */ public void showNote(int noteNumber) { if(noteNumber < numberOfNotes() && noteNumber >= 0) { // This is a valid note number. System.out.println(notes.get(noteNumber)); } else { System.out.println("There is no note "+noteNumber+"!!"); } } /** * Remove a note from the notebook if it exists. * @param noteNumber The number of the note to be removed. */ public void removeNote(int noteNumber) { if(noteNumber < numberOfNotes() && noteNumber >= 0) { // This is a valid note number. notes.remove(noteNumber); } } /** * List all notes in the notebook. * We'll call these "for-each loops". The body of the loop runs * once for each item in the ArrayList. To the right of : is the * ArrayList to "process". To the left is a variable declaration * for a variable to hold ONE item from the collection. Java * automatically copies each item, in turn, from the list to the * local variable and runs the code in the "body". */ public void listAllNotes() { for(String note : notes) { System.out.println(note); } } /** * List the notes of length 10 or greater. */ public void listLongNotes() { for(String note : notes) { if (note.length() >= 10) { System.out.println(note); } } } /** * List all notes in the notebook, but with numbers in front. */ public void listAllNotesWithNumber() { int num = 0; for(String note : notes) { System.out.println(num+": "+note); num = num + 1; // Make it bigger for next print statement } } /** * Count up the total length of all notes in the notebook and return that sum. * @return The sum of the lengths of the notes. */ public int totalNoteLengths() { int totalLength = 0; for(String note : notes) { totalLength = totalLength + note.length(); } return totalLength; } /** * Print the notes in the notebook containing a * particular search term. */ public void showNotesContaining(String term) { for(String note : notes) { if (note.contains(term)) { System.out.println(note); } } } /** * Return the position of the first note in the notebook that * matches the search term * @param term The search term we're looking for */ public int indexOfFirstMatch(String term) { int num = 0; for(String note : notes) { if (note.contains(term)) { return num; } num = num + 1; } // If we didn't leave early due to the return statement above, we must // have checked each note and didn't find any maches. Time to return -1. return -1; // Didn't find it anywhere } /** * Return the position of the first note in the notebook that * matches the search term. This time we're writing it with a * while loop, since we only have to keep searching "while" we * haven't found a match. * @param term The search term we're looking for */ public int indexOfFirstMatch_while(String term) { int i = 0; // Index of the first note to check while (i < notes.size() && !notes.get(i).contains(term)) { i = i+1; } // There are TWO reasons why the loop might stop: We found // a match, or we ran out of notes to check. In the first case // we want to return i, in the second case return -1. if (i < notes.size()) { // Must have stopped early... return i; } else { return -1; // Must've tried them all without success } } /** * Similar to the method above, but collects all of the notes * that contain the search term and RETURNS them in a new list. * @param term The search term we're looking for * @return An ArrayList containing the "hits" */ public ArrayList getNotesContaining(String term) { ArrayList keepers = new ArrayList(); // To hold "keepers" for(String note : notes) { if (note.contains(term)) { keepers.add(note); } } return keepers; } /** * This method will quickly add a bunch of notes to the * notebook for testing purposes. * * @param numToAdd The number of notes I want */ public void addManyNotes(int numToAdd) { int count = 0; while (count < numToAdd) { notes.add("This is note number "+count); count = count + 1; } } /** * Now that we know about for loops, and that count-controlled loops * should be expressed via a for loop for good style, we should really * rewrite this method to use a for loop... * * @param numToAdd The number of notes I want */ public void addManyNotes_for(int numToAdd) { for (int count = 0; count < numToAdd; count = count + 1) { notes.add("This is note number "+count); } } /** * Pointing out that while is more general than for-each. We can * use it to do the same things that a for-each does, but we can * also do things like rolling a die N times that we CAN'T do with * a for-each loop. Stylistically we should have used a for-each * here, but I wanted to make the point... */ public void listAllNotes_while() { int count = 0; while (count < notes.size()) { System.out.println(notes.get(count)); count = count + 1; } } /** * Points out that there are times we might need to use a loop * other than for-each, even when processing a collection. */ public void listAllBackwards() { int count = notes.size()-1; while (count >= 0) { System.out.println(notes.get(count)); count = count - 1; } } }