Textbook: Data Structures and the Java Collections Framework 3rd Edition by William Collins William...

Post on 04-Jan-2016

244 views 3 download

Transcript of Textbook: Data Structures and the Java Collections Framework 3rd Edition by William Collins William...

Textbook:

Data Structures and the Java Collections Framework 3rd Edition

by William Collins 

Chapter 0

Introduction to

Java

Basically, a class consists of: 1) variables called fields

together with 2) functions called methods

that act on those fields.

The following class, HelloWorld, has no fields and defines only one method, a special method called main, whose execution entails the calling of another method, println:

public class HelloWorld{

public static void main (String [ ] args){System.out.println ("Hello, world!"); }

} // class HelloWorld

The output from the execution of this program is

Hello, world!

A primitive type is a collection of values, together with operations that can be performed on those values.

For example, the int type consists of all integer values in the range from −2,147,483,648 to 2,147,483,647, inclusive.

The operations that can be performed on those values include addition, subtraction , multiplication, division, and remainder. The division operator, /, returns the result of truncated integer division, so 14 / 3 returns 4. The remain-der operator, %, returns the integer remainder from integer division, so 14 % 3 returns 2.

We can declare variables of type int, and assign values to those variables:

int first,

last;

first = 14 / 3;

last = 14 % 3 + 7;

In addition to variables whose type is primitive, Java also has objects.

An object – sometimes called an instance of a class – is a variable whose type is a class.

An object has the fields and can call the methods of its class.

Let’s look at the

String class

A String object is a variable that contains a string (a sequence of characters) and can call methods in the String class.

Objects cannot be explicitly declared in Java; instead, programmers declare object reference variables.

String s;s is not a String object,

but rather a String reference,

a variable that can hold the

address of a String object.

To store the address of a String object in s,we will:

1. Allocate space for a new String object.

2. Initialize the fields in that object.

3. Assign to s the address of that object.

All three of these tasks can be accomplished in a single assignment:

s = new String();

A method with the same name as the class is called a constructor.

The purpose of a constructor is to initialize the object’s fields.

A class’s default constructor has no parameters.

The String class’s default constructor

initializes the fields

so that the String object

represents an empty string.

Another constructor in the String class has a String reference parameter. Here’s the heading

parameter

public String (String original)

And here is a statement that calls that constructor:

String t = new String (“Aloha”);

argument

Actually, the argument is a reference to “Aloha”.

Now, the String objects referenced by s and t can invoke String methods:

s.length() // returns 0

t.toLowerCase() // returns (a reference to)

// “aloha” . t is still a

// reference to “Aloha”

/**

* Returns the index within this String object

* of the first occurrence of the specified

* substring.

* @param str – the specified substring

* @return the index of the first occurrence

* of str in this String object, or –1

* if str is not a substring of this

* String object

* @throws NullPointerException – if str is null

*/

public int indexOf (String str)

The JAVADOC comments plus the method heading constitute the method specification – the user’s view of the method.

Determine the output:

System.out.println (t.indexOf (“ha”));

System.out.println (t.indexOf (“a”));

System.out.println (s.indexOf (“ha”));

Hint: Indexes start at 0.

ANS: 3

4

null pointer exception

String w = null;

w does not contain the address of any String object,

so w cannot be used to call any String methods.

The equals method tests for equality of objects

The == operator tests for equality of references.

String z = new String (“Aloha”);

Determine the result returned in each case:

s.equals (“”)

s == “”

t.equals (“Aloha”)

t == “Aloha”

t.equals (null)

t.equals (z)

t == z

w.equals (null)

w == null

s.equals (“”) ANS:

s == “”

t.equals (“Aloha”)

t == “Aloha”

t.equals (null)

t.equals (z)

t == z

w.equals (null)

w == null

String y1 = “Aloha”;

String y2 = “Aloha”;

These statements create two references, y1 and y2, to the same string object, so

y1 == y2 // returns true

y1 == t // returns false

but

y1.equals (t) // returns true

LOCAL VARIABLES

A local variable is one that is declared within a method, including the method’s parameters.

For example, the following method, with 3 local variables, returns the sum of the first n positive integers:

/**

* Returns the sum of the integers from 1 up to a given integer.

* @param n – the given positive integer.

* @return the sum of the first n positive integers.

*/

public static int sumUp (int n)

{

int sum = 0;

for (int i = 1; i < n; i++)

sum += i; // same as sum = sum + i;

return sum;

} // method sumUp

Local variables must be initialized before they can be used. For example, method sumUp initialized its local variable sum to 0. The following method initializes its local variable last to 20. When sumUp is called, its local variable n is initialized to 20:

public void run( )

{

int last = 20;

System.out.println (sumUp (last));

} // method run

But the following version would generate a compile-time error (“variable last may not have been initialized”):

public void run( )

{

int last;

System.out.println (sumUp (last));

} // method run

The Scanner Class

The Scanner class allows users easy access to text data. A text is a sequence of lines, separated by end-of-line markers. A Scanner object skips over irrelevant characters called delimiters (for example, spaces) to access tokens (for example, integers).

The text can 1) be entered from the keyboard, 2) be entered from a file, or 3) consist of a string of characters. The Scanner class has constructors to initialize each of the three kinds of Scanner object.

Scanner keyboardScanner = new Scanner (System.in);

int n = keyboardScanner.nextInt();

Suppose the input from the keyboard is

74

Then the token 74 will be stored in the variable n.

Scanner keyboardScanner = new Scanner (System.in);

int j, k, m, n;

j = keyboardScanner.nextInt();

k = keyboardScanner.nextInt();

m = keyboardScanner.nextInt();

Suppose the input from the keyboard is

74 58

0

The delimiters are whitespace characters: spaces, tabs, end-of-line markers, and so on). They are skipped over, and the tokens 74, 58 and 0 will be assigned to the variables j, k and m, respectively.

The hasNextInt method tests to see if the next token is an int value:

Scanner keyboardScanner = new Scanner (System.in);

int bonus;

if (keyboardScanner.hasNextInt())

bonus = keyboardScanner.nextInt();

else

bonus = 0;

The Scanner class also has methods to scan in and check for other primitive values, such as nextDouble(), nextLong(), hasNextDouble(), …

The next() method scans in the next token as a string of characters:

Scanner keyboardScanner = new Scanner (System.in);

String s = keyboardScanner.next();

Suppose the input from the keyboard is

gentle

Then the variable s will contain a reference to the string “gentle”.

The next() method can help with the scanning of dirty data. Assume the keyboard input is supposed to consist of positive int values, ending with a value of -1 (such a terminal value is called a sentinel);

final int SENTINEL = -1;

Scanner keyboardScanner = new Scanner (System.in);

int sum = 0,

score;

while (true)

if (keyboardScanner.hasNextInt())

{

score = keyboardScanner.nextInt();

if (score == SENTINEL)

break; // terminate execution of loop

sum += score;

} // if next token is an int

else

keyboardScanner.next();

System.out.println (sum);

Suppose the input entered from the keyboard is

90 100 50

7z 80

5o

-1

The preceding loop would be executed seven times, but the erroneous values 7z and 5o would be skipped over. The output would be

320

If the else part of the preceding if statement were omitted, an infinite loop would occur because 7z would fail the hasNextInt() condition. Suppose the entire body of the loop were replaced with

score = keyboardScanner.nextInt();

if (score == SENTINEL)

break; // terminate execution of loop

sum += score;

Then an error (technically, an exception, as defined in Chapter 2) would occur at run time because 7z is not an int value.

Sometimes the remainder of an input line should be skipped over if an incorrect value is discovered during scanning. For example, it might be that each input line is supposed to contain a name, grade point average, class year and age, with “***” as the sentinel. If the grade point average is not a double value (or the class year or age is not an int value), the rest of the line should be skipped.

final String SENTINEL = “***”;

Scanner keyboardScanner = new Scanner (System.in);

String name;

int classYear,

age;

double gpa;

while (true)

{

name = keyboardScanner.next();

if (name.equals (SENTINEL))

break;

if (!keyboardScanner.hasNextDouble())

{

keyboardScanner.nextLine();

continue; // start another iteration of the loop

} // if next token is not a double

gpa = keyboardScanner.nextDouble();

if (!keyboardScanner.hasNextInt())

{

keyboardScanner.nextLine();

continue; // start another iteration of loop

} // if next token is not an int

classYear = keyboardScanner.nextInt();

if (!keyboardScanner.hasNextInt())

{

keyboardScanner.nextLine();

continue; // start another iteration of loop

} // if next token is not an int

age = keyboardScanner.nextInt();

// process name, gpa, classYear and age …

} // while

For scanning over a file, the constructor is different from keyboard scanning, but the “hasNext(), hasNextInt(), next(), nextDouble(), …” methods are still available. For example,

Scanner fileScanner = new Scanner (new File (“data”));

if (fileScanner.hasNextDouble())

double gpa = fileScanner.nextDouble();

else

fileScanner.next();

Sentinels are not used in file scanning because it is too easy to forget to append the sentinel to the end of the file. (With keyboard input, a scan loop will continue until the sentinel is entered.) So a typical scanning loop with fileScanner will start with

while (fileScanner.hasNext())

or

while (fileScanner.hasNextLine())

or

while (fileScanner.hasNextInt())

or …

Scanning over a line is fairly straightforward. For example, suppose we want to add up the int values in a line, and skip over the non-int values.

Scanner lineScanner = new Scanner (“70 o2 50”);

int sum = 0;

while (lineScanner.hasNext())

if (lineScanner.hasNextInt())

sum += lineScanner.nextInt();

else

lineScanner.next(); // skip non-int

Often a program needs all three kinds of Scanner object: a keyboard scanner to get the name of a file, a file scanner to access each line in that file, and a line scanner to access the tokens in a line.

You can specify the delimiters for your scanner with the useDelimiter method. For example, if you want the tokens in a string line to be upper- or lower-case letters, any other character will be a delimiter:

Scanner sc = new Scanner (line).useDelimiter ("[^a-zA-Z]+");

In the argument of the above call to the useDelimiter method, the ‘+’ can be read as “one or more occurrences” and ‘^’ means “except”. So a delimiter is one or more occurrences of any character except a letter.

Exercise:

Create a keyboard scanner in which the tokens are unsigned integers, and write the code to determine the sum of the integers.

Note: -5 will be scanned as the unsigned integer 5, and the minus sign will be skipped over as a delimiter.

Arrays

An array is a collection of elements, of the same type, that can be stored one after the other in memory. For example, we can create an array object of 10 double values as follows:

double[ ] weights = new double[10];

This array of double values is automatically initialized to 0.0 by the Java Virtual Machine. The values are stored at indexed locations, starting at index 0, and weights is a reference to the element at index 0.

We can fill up the array:

for (int j = 0; j < 10; j++)

weights[j] = j;

The int values of j are converted to double values, so we have weights[0] = 0.0, weights[1] = 1.0, weights[2] = 2.0, …, weights[9] = 9.0. The length field in an array object holds the capacity of the array, that is, the number of indexes. So System.out.println (weights.length) would print out 10, but because array indexes start at 0, weights[10] is illegal.

The capacity of an array object can be set explicitly at run time:

Scanner sc = new Scanner (System.in);

int n = sc.nextInt();

double[ ] weights = new double[n];

Or implicitly:

double [ ] weights = {107.3, 112.1, 114.4, 119.0, 117.4};

The value stored in the length field is 5.

Arguments

and

Parameters

When a method is called, the arguments are the expressions (separated by commas) inside the parentheses following the method identifier.

In the declaration of a method, the parameters are the variables (each preceded by its type, and separated by commas) inside the parentheses following the method identifier.

The relationship between an argument and its corresponding parameter is, at least apparently, simple: A copy of the value of the argument is stored in the parameter. For example, suppose we have

public void run( )

{

int last = 20;

System.out.println (sumUp (last));

} // method run

public static int sumUp (int n)

{

int sum = 0;

for (int i = 1; i < n; i++)

sum += i; // same as sum = sum + i;

return sum;

} // method sumUp

When the call to sumUp is made in the run method, a copy of the argument’s value, 20, is stored in the parameter n, the sumUp method is executed, and 110 is returned and printed in the run method.

Because a copy of the argument is stored in the parameter, the argument itself is unaffected by the call. For example, here is a method that swaps the values of its two parameters:

public static void swap (int a, int b)

{

int temp = a;

a = b;

b = temp;

} // method swap

Here is a call to the swap method:

int a = 15,

b = 6;

swap (a, b);

System.out.println (a + “ “ + b);

What will the output be?

The output will be

15 6

Because the value of the arguments a and b are unchanged by the call to the method swap. The values of the parameters a and b are swapped, but that has no effect on the arguments.

If the argument is a reference, the argument will be unchanged by a method call, but the object referenced may be changed. For example,

public void swap (double[ ] a, int i, int j){

double temp = a[i];a[i] = a[j];a[j] = temp;

} // method swap

What will the output be from the following call:

double [ ] x = {5.0, 8.0, 12.2, 20.0};swap (x, 1, 2);System.out.println (x [1] + “ " + x [2]);

The argument x is unchanged (and, certainly, the constants 1 and 2 are unchanged), but the array object referenced by x is changed, and the output is

12.2 8.0