Exercise 22.5: Given a certain number of six-sided dice, you can calculate the theoretical probability of each
possible total. For example, with two six-sided dice, the probability of a total of seven is one in six. Write a
program that compares the theoretical distribution of sums for a given number of six-sided dice with the
actual results over a large number of "rolls" using Random to generate numbers between one and six. Does it
matter which of the number-generating methods you use?
Exercise 22.6: Write a program that tests nextGaussian, displaying the results of a large number of runs
as a graph (a bar chart of * characters will do).
22.5. Scanner
The Scanner class will help you read files of formatted data, such as those you might generate from a
method that used printf. It uses regular expressions to locate the desired data, and parsers to convert them
into known types. For example, it knows how to use localized number parsing to read in values that humans
might type (such as "20,352").
Many of the methods of Scanner can take a pattern to indicate how the scanner should match input. These
methods all have two overloaded forms: One takes the pattern as a String and the other takes it as a
java.util.regex.Pattern.When we say that a method takes a pattern, you should infer from this that
there are two variants of the method as just described. Supplying a pattern as a string may require that it be
compiled each time (using Pattern.compile), so if a pattern is to be reused it may be more efficient to
use a Pattern object directly. See Section 13.3 on page 321 for a refresher on regular expression patterns.
There are two primary approaches to using Scanner, although they can be reasonably intermixed as desired,
with care. The first is to use it to read a stream of values. The second is line-oriented.
22.5.1. Stream of Values
When reading input as a stream of values, you simply ask Scanner to return the next value in the stream.
The scanner determines the next value by first skipping over any delimiter characters in the input (which by
default matches whitespace) and examining the input up to the next delimiter. For example, the following
code is a rewrite of the sumStream example from page 533:
static double sumStream(Readable source) throws IOException {
Scanner in = new Scanner(source);
double result = 0.0;
while (in.hasNext()) {
if (in.hasNextDouble())
result += in.nextDouble();
else
in.next();
}
IOException ex = in.ioException();
if (ex != null)
throw ex;
return result;
}
You can iterate through the input one token at a time, asking if the next token is a string, int, or double
value, and so forth, and storing it into a variable of the appropriate type.[2] In contrast to
StreamTokenizer, Scanner can produce primitive values other than just double, and it recognizes
numbers in a range of formats, not just the common decimal format. (Essentially, how ever Formatter see