420 likes | 589 Views
Java. Lists and Files. Objectives. Be able to use ArrayLists : Create Initialize Add elements Retrieve elements Pass as arguments to methods Return from methods Be able to use Random to get a random number Be able to parse input from a file Be able to write output to a file.
E N D
Java Lists and Files
Objectives • Be able to use ArrayLists: • Create • Initialize • Add elements • Retrieve elements • Pass as arguments to methods • Return from methods • Be able to use Random to get a random number • Be able to parse input from a file • Be able to write output to a file
Example: Analysis and Design • We’d like to make a guessing game that drills students on the countries of the world. • Elements: • A GUI controller; • A Game class that: • Represents a list of countries; • Randomly chooses a country as the current answer; • Produces a sequence of hints. • A Country class that: • Represents stuff about countries. Some hint goes here (maybe an image and/or text)… Your guess… Give up
Limitations of Arrays • Our initial iteration assumes that: • We know how many countries there are; • We’re happy with the low-level array methods. • Moving beyond these assumptions forces us to give up arrays because arrays: • Are fixed in size at compile time; • Have a limited set of predefined methods.
Lists • Java’s List data structure is more flexible: • Lists can grow or shrink at run time. • Lists provide more predefined behaviors. • The Java Collections framework provides classes supporting groups of objects: • List<> specifies an interface for an ordered collection of typed objects; • ArrayList<>implements the List<> interface using an array.
The ArrayList Class • ArrayLists store an array of typed objects. List<aType> aList = new ArrayList<aType>(); sizearray aList 0
ArrayLists: Adding Values (add) • ArrayLists handle their own memory allocation. List<aType> aList = new ArrayList<aType>(); aList.add(aTypeObject); sizearray 1 [0] [1] … [m-1] aList aTypeObject
ArrayLists: Accessing Values (get) • ArrayLists provide indexed access. List<aType> aList = new ArrayList<aType>(); aList.add(aTypeObject); System.out.println(aList.get(arrayIndex)); sizearray aList [0] [1] … [m-1] 1 aTypeObject
ArrayLists: Memory Allocation • ArrayLists allocate memory automatically. List<aType> aList = new ArrayList<aType>(); aList.add(aTypeObject); System.out.println(aList.get(arrayIndex)); aList.add(a2ndTypeObject); ... aList.add(anM+1stTypeObject); sizearray aList [0] [1] … [m-1][m] … m+1 aTypeObject a2ndTypeObject anM+1stTypeObject
Random • To get a random number in Java, create a random number generator: Random randomGenerator = new Random(); • The generator will return a new random number each time it is asked to do so: int randomNumber1 = randomGenerator.nextInt(); int randomNumber2 = randomGenerator.nextInt(15); double randNumber3 = randomGenerator.nextDouble();
Using lists for our example • We’d like to have an arbitrary number of countries in the “list”. • We’ll keep the same GUI controller, but will create an arbitrarily long List of country name Strings. • Upgrade the CountryGuessGame to use lists rather than arrays. The results of this programming should be as follows: • CountryGuessController1 should not change; • CountryGuessGameshould end up looking like CountryGuessGame1 (handout).
package c12lists.lecture.countryguess; importjava.util.ArrayList; importjava.util.List; importjava.util.Random; publicclassCountryGuessGame{ private List<String> myCountries; privateintmyAnswerIndex, myHintCount; private Random myRandom; publicCountryGuessGame() { myCountries = newArrayList<String>(); myCountries.add("Honduras"); myCountries.add("Panama"); myRandom = new Random(); reset(); } publicvoid reset() { myAnswerIndex = myRandom.nextInt(myCountries.size()); myHintCount = 0; } //continued on next slide
//continued from previous slide publicboolean guess(String text) { returnmyCountries.get(myAnswerIndex).equalsIgnoreCase(text); } public String getAnswer() { returnmyCountries.get(myAnswerIndex); } public String getHintText() { myHintCount++; String name = myCountries.get(myAnswerIndex); if (myHintCount == 1) { return"The name starts with '" + name.charAt(0) + "'"; } elseif (myHintCount == 2) { return"The name has " + name.length() + " letters"; } elseif (myHintCount == 3) { return"The name ends with '" + name.charAt(name.length() - 1) + "'"; } else { return"no more hints"; } } } //ends CountryGuessGame class
Array & Lists Syntax String[] myCountries = new String[2]; myCountries[0] = "Honduras"; myCountries[1] = "Panama"; System.out.println(myCountriesArray.length); System.out.println(myCountriesArray[0]); List<String> myCountriesList = new ArrayList<String>(); myCountriesList.add("Honduras"); myCountriesList.add("Panama"); System.out.println(myCountriesList.size()); System.out.println(myCountriesList.get(0));
ArrayLists: As Parameters • ArrayLists can be passed as parameters. private int count(List<Country> countries, String continent) { int result = 0; for (inti = 0; i < countries.size(); i++) { if (countries.get(i).getContinentName() .equalsIgnoreCase(continent)) { result++; } } return result; }
ArrayLists: As Return values • ArrayLists can be returned as return values. private List<Country> loadCountries() { List<Country> result = new ArrayList<Country>(); result.add(new Country("Algeria", "Africa")); result.add(new Country("Angola", "Africa")); ... return result; }
ArrayList: Copying List<Country> original = new ArrayList<Country>(); // add two country objects to original (c1 & c2)… List<Country> referenceCopy = original; List<Country> shallowCopy = (List<Country>)original.clone(); sizearray original 2 referenceCopy c1 c2 sizearray shallowCopy 2
List<Country> deepCopy = deepCopy(original); public List<Country> deepCopy(List<Country> original) { List<Country> result = new ArrayList<Country>(); for (inti = 0; i < original.size(); i++) result.add(new Country(myCountries.get(i).getName(), myCountries.get(i).getContinentName(), myCountries.get(i).getImageName())); return result; } sizearray deepCopy 2 c1copy c2Copy
ArrayList Equality • Similar issues arise when checking arraylist equality: • anArrayList.equals(anotherArrayList) checks the two lists are the same size and that their corresponding elements are equals(). • This works for lists of strings, but special equality checking routines must be written for lists of other types. • The String class has an equals() operator that checks string equality properly.
Multi-Dimensional Lists • Lists can also be multi-dimensional. • Declaring 2-D lists: ArrayList<ArrayList<RType>> ID • Initializing 2-D lists: new ArrayList<ArrayList<RType>>(rowsize) • Accessing 2-D array elements: ID.get(row).get(column) • Multidimensional arrays are generally easier to use and more efficient.
Multi-dimensional List Structures • Multi-dimensional lists are useful for more general multi-dimensional structures. • Example:
Example: Character Drill • We’d like to modify the guessing game so that drills students on Chinese Characters. • A sketch of a solution achieving this goal is shown here. Some hint goes here (maybe an image and/or audio)… User’s guess… Give up
Example: Design • The design includes the following classes:
Limitations of Hard-Coding Data • Our initial iteration assumes that: • we can code the data directly in the program; • the data never (or rarely) changes; • people who change data know how to program. • This approach does not scale well to real data-based applications.
Input & Output Streams • Input and output in Java is accomplished using stream classes: Input Stream Program Output Stream Program
Java Streams • Simple I/O uses predefined streams: • System.in • System.out • System.err • Create file streams using: • File • Scanner • PrintWriter
File • The File class models a system-independent view of a file comprising: • Filename; • Directory pathname: • Relative; • Absolute. • Patterns: new File(pathAndFilenameString) new File(pathnameString, filenameString)
Scanner • The Scanner class can scan: • Keyboard input stream; • File; • String. • Pattern: new Scanner(inputStreamOrFileOrString) • The API includes these methods: • next() nextInt() nextLine() ... • hasNext() hasNextInt() hasNextLine() ... • close()
Example: Compute Statistics Problem: Compute statistics for a file of quiz scores. Given: the data filename and path Algorithm: • Open a read stream/scanner to the given file. • While the file has more tokens: • Read the token. • Process the token. • Close the file stream/scanner.
Statistics Solution Structure import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Statistics { public static final String PATH = “src/c11files/examples/data/”; //main method will go here ... //compute methods will go here ... } Method implementations on next slides
public static void main(String[] args) { Scanner keyboard = new Scanner(System.in); System.out.print("Data filename: "); String filename = keyboard.next(); try{ Scanner fileIn = new Scanner(new File(PATH, filename)); List<Integer> scores = new ArrayList<Integer>(); while (fileIn.hasNext()) { scores.add(fileIn.nextInt()); } fileIn.close(); System.out.println(scores); double average = computeAverage(scores); System.out.printf("average: %5.2f%n", average); System.out.printf("std dev: %5.2f%n", computeVariance(scores, average)); } catch(FileNotFoundException e){ System.out.println("Invalid file indicated."); } }
public static double computeVariance( List<Integer> values, double average) throws Exception { if (values == null || values.size() == 0) { throw new Exception("Empty list"); } int sum = 0; for (inti = 0; i < values.size(); i++) { sum += Math.pow(values.get(i) - average, 2); } return Math.sqrt(sum / values.size()); }
public static double computeAverage(List<Integer> values) throws Exception { if (values == null || values.size() == 0) { throw new Exception("Empty list"); } int sum = 0; for (inti = 0; i < values.size(); i++){ sum += values.get(i); } return sum / values.size(); }
Example: Record Input Problem: Read in soldier data from a file. Soldiers may or may not have nickname(s). Given: the data filename and path Algorithm: • Open a read stream/scanner to the given file. • While the file has more lines: • Read the line. • Process the fixed and variant tokens. • Close the file stream/scanner.
public class ReadRecordsConsole { public static final String PATH = "src/c11files/examples/data/"; public static void main(String[] args) { try{ Scanner keyboard = new Scanner(System.in); System.out.print("Data Records filename: "); String filename = keyboard.next(); Scanner fileIn = new Scanner(new File(PATH, filename)); List<Soldier> soldiers = new ArrayList<Soldier>(); while (fileIn.hasNextLine()) { soldiers.add(new Soldier(fileIn.nextLine())); } fileIn.close(); for (int i = 0; i < soldiers.size(); i++) { System.out.println(soldiers.get(i)); } } catch(FileNotFoundException e){ System.out.println("Invalid File indicated."); } } }
public class Soldier { private String myName, myRank, mySerialNumber; private List<String> myNickNames; public Soldier(String line) { Scanner scanner = new Scanner(line); myName = scanner.next(); myRank = scanner.next(); mySerialNumber = scanner.next(); myNickNames = new ArrayList<String>(); while (scanner.hasNext()) { myNickNames.add(scanner.next()); } scanner.close(); } public String toString() { String result = myName + " " + myRank + " " + mySerialNumber; for (int i = 0; i < myNickNames.size(); i++) { result += " " + myNickNames.get(i); } return result; } }
PrintWriter • The PrintWriter class can print formatted text to a text-output stream. • Pattern: new PrintWriter(outputFile) • The API includes these methods: • print() println() ... • printf() • close() flush()
Example: File Output Problem: Get data from the user, put it into a file. Given: the output filename and path Algorithm: • Open a print writer stream to the given file. • Loop forever: • Prompt for and read a line of data. • If the line is the sentinel • Quit. • else • Output the line. • Close the file stream/scanner.
ExampleImplementation PrintWriterfileOut = new PrintWriter(new File(path, filename)); String line = ""; while (true) { System.out.print("enter record (just enter to quit): "); line = keyboard.nextLine(); if (line.equals("")) { break; } else { fileOut.println(line); } } fileOut.close(); System.out.println("data stored to: " + path + filename);