1 / 55

Chapter 11—Arrays and ArrayLists

Java. The Art and Science of. An Introduction. to Computer Science. ERIC S. ROBERTS. C H A P T E R 1 1. Arrays and ArrayLists. Chapter 11—Arrays and ArrayLists. Little boxes, on a hillside, little boxes made of ticky-tacky Little boxes, little boxes, little boxes, all the same

Télécharger la présentation

Chapter 11—Arrays and ArrayLists

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Java The Art and Science of An Introduction to Computer Science ERIC S. ROBERTS C H A P T E R 1 1 Arrays and ArrayLists Chapter 11—Arrays and ArrayLists Little boxes, on a hillside, little boxes made of ticky-tacky Little boxes, little boxes, little boxes, all the same There’s a green one and a pink one and a blue one and a yellow one And they're all made out of ticky-tacky and they all look just the same —Malvina Reynolds, “Little Boxes,” 1962 11.1 Introduction to arrays 11.2 Internal representation of arrays 11.3 Passing arrays as parameters 11.4 Using arrays for tabulation 11.5 Initialization of arrays 11.6 Multidimensional arrays 11.7 Image processing 11.8 The ArrayList class

  2. 1. An array is ordered. You must be able to count off the values: here is the first, here is the second, and so on. 2. An array is homogeneous. Every value in the array must have the same type. Introduction to Arrays • An array is a collection of individual data values with two distinguishing characteristics: • The individual values in an array are called elements. The type of those elements (which must be the same because arrays are homogeneous) is called the element type. The number of elements is called the length of the array. • Each element is identified by its position number in the array, which is called its index. In Java, index numbers always begin with 0 and therefore extends up to one less than the length of the array.

  3. Declaring an Array Variable • As with any other variable, array variables must be declared before you use them. In Java, the most common syntax for declaring an array variable looks like this: type[]name = new type[n]; where type is the element type, name is the array name, and n is an integer expression indicating the number of elements. • This declaration syntax combines two operations. The part of the line to the left of the equal sign declares the variable; the part to the right creates an array value with the specified number of elements and then assigns it to the array variable. • Even though the two operations are distinct, it will help you avoid errors if you make a habit of initializing your arrays when you declare them.

  4. This easiest way to visualize arrays is to think of them as a linear collection of boxes, each of which is marked with its index number. You might therefore diagram the intArray variable by drawing something like this: intArray 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 An Example of Array Declaration • The following declaration creates an array called intArray consisting of 10 values of type int: int[] intArray = new int[10]; • Java automatically initializes each element of a newly created array to its default value, which is zero for numeric types, false for values of type boolean, and null for objects.

  5. You can, for example, select the initial element by writing intArray[0] • The result of a selection operation is essentially a variable. In particular, you can assign it a new value. The following statement changes the value of the last element to 42: intArray[9] = 42; 42 Array Selection • Given an array such as the intArray variable at the bottom of this slide, you can get the value of any element by writing the index of that element in brackets after the array name. This operation is called selection. intArray 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9

  6. The standard for loop pattern that cycles through each of the array elements in turn looks like this: for (int i = 0; i < array.length; i++) { Operations involving the ith element of the array } Selecting the length field returns the number of elements. • As an example, you can reset every element in intArray to zero using the following for loop: for (int i = 0; i < intArray.length; i++) { intArray[i] = 0; } Cycling through Array Elements • One of the most useful things about array selection is that the index does not have to be a constant. In many cases, it is useful to have the index be the control variable of a for loop.

  7. Exercise: Summing an Array Write a method sumArray that takes an array of integers and returns the sum of those values. /** * Calculates the sum of an integer array. * @param array An array of integers * @return The sum of the values in the array */ private int sumArray(int[] array) { int sum = 0; for (int i = 0; i < array.length; i++) { sum += array[i]; } return sum; }

  8. There are two standard approaches for shifting between Java and human-readable index numbers: 1. Use Java’s index numbers internally and then add one whenever those numbers are presented to the user. 2. Use index values beginning at 1 and ignore element 0 in each array. This strategy requires allocating an additional element for each array but has the advantage that the internal and external index numbers correspond. Human-Readable Index Values • From time to time, the fact that Java starts index numbering at 0 can be confusing. In particular, if you are interacting with a user who may not be Java-literate, it often makes more sense to let the user work with index numbers that begin with 1.

  9. Arrays and Graphics • Arrays turn up frequently in graphical programming. Any time that you have repeated collections of similar objects, an array provides a convenient structure for storing them. • As a aesthetically pleasing illustration of both the use of arrays and the possibility of creating dynamic pictures using nothing but straight lines, the text presents the YarnPattern program, which simulates the following process: • Place a set of pegs at regular intervals around a rectangular border. • Tie a piece of colored yarn around the peg in the upper left corner. • Loop that yarn around the peg a certain distance DELTA ahead. • Continue moving forward DELTA pegs until you close the loop.

  10. A Larger Sample Run YarnPattern

  11. The YarnPattern Program import acm.graphics.*; import acm.program.*; import java.awt.*; /** * This program creates a pattern that simulates the process of * winding a piece of colored yarn around an array of pegs along * the edges of the canvas. */ public class YarnPattern extends GraphicsProgram { public void run() { initPegArray(); int thisPeg = 0; int nextPeg = -1; while (thisPeg != 0 || nextPeg == -1) { nextPeg = (thisPeg + DELTA) % N_PEGS; GPoint p0 = pegs[thisPeg]; GPoint p1 = pegs[nextPeg]; GLine line = new GLine(p0.getX(), p0.getY(), p1.getX(), p1.getY()); line.setColor(Color.MAGENTA); add(line); thisPeg = nextPeg; } } page 1 of 2 skip code

  12. /* Initializes the array of pegs */ private void initPegArray() { int pegIndex = 0; for (int i = 0; i < N_ACROSS; i++) { pegs[pegIndex++] = new GPoint(i * PEG_SEP, 0); } for (int i = 0; i < N_DOWN; i++) { pegs[pegIndex++] = new GPoint(N_ACROSS * PEG_SEP, i * PEG_SEP); } for (int i = N_ACROSS; i > 0; i--) { pegs[pegIndex++] = new GPoint(i * PEG_SEP, N_DOWN * PEG_SEP); } for (int i = N_DOWN; i > 0; i--) { pegs[pegIndex++] = new GPoint(0, i * PEG_SEP); } } /* Private constants */ private static final int DELTA = 67; /* How many pegs to advance */ private static final int PEG_SEP = 10; /* Pixels separating each peg */ private static final int N_ACROSS = 50; /* Pegs across (minus a corner) */ private static final int N_DOWN = 30; /* Pegs down (minus a corner) */ private static final int N_PEGS = 2 * N_ACROSS + 2 * N_DOWN; /* Private instance variables */ private GPoint[] pegs = new GPoint[N_PEGS]; } The YarnPattern Program import acm.graphics.*; import acm.program.*; import java.awt.*; /** * This program creates a pattern that simulates the process of * winding a piece of colored yarn around an array of pegs along * the edges of the canvas. */ public class YarnPattern extends GraphicsProgram { public void run() { initPegArray(); int thisPeg = 0; int nextPeg = -1; while (thisPeg != 0 || nextPeg == -1) { nextPeg = (thisPeg + DELTA) % N_PEGS; GPoint p0 = pegs[thisPeg]; GPoint p1 = pegs[nextPeg]; GLine line = new GLine(p0.getX(), p0.getY(), p1.getX(), p1.getY()); line.setColor(Color.MAGENTA); add(line); thisPeg = nextPeg; } } page 2 of 2

  13. A Digression on the ++ Operator • The YarnPattern program illustrates a new form of the ++ operator in the various statements with the following form: pegs[pegIndex++] = new GPoint(x,y); • The pegIndex++ expression adds one to pegIndex just as if has all along. The question is what value is used as the index, which depends on where the ++ operator appears: • If the ++ operator comes after a variable, the variable is incremented after the value of the expression is determined. Thus, in this example, the expression pegs[pegIndex++] therefore selects the element of the array at the current value of pegIndex and then adds one to pegIndex afterwards, which moves it on to the next index position. • If the ++ operator comes before a variable, the variable is incremented first and the new value is used in the surrounding context. • The -- operator behaves similarly but subtracts one from the variable instead.

  14. Consider, for example, the following declaration: double[] scores = new double[5]; • The variable scores is allocated on the stack and is assigned the address of a newly allocated array in the heap: heap stack 1000 length 1004 5 1008 0.0 scores[0] 1010 0.0 scores[1] scores FFFC 1000 1018 0.0 scores[2] 1020 0.0 scores[3] 1028 0.0 scores[4] Internal Representation of Arrays • Arrays in Java are implemented as objects, which means that they are stored in the heap. The value stored in an array variable is simply a reference to the actual array.

  15. 1. 2. 3. 4. Generates an array containing the integers 0 to N-1. Prints out the elements in the array. Reverses the elements in the array. Prints out the reversed array on the console. • The next slide contains a simulated version of a program that performs the following actions: Passing Arrays as Parameters • When you pass an array as a parameter to a method or return a method as a result, only the reference to the array is actually passed between the methods. • The effect of Java’s strategy for representing arrays internally is that the elements of an array are effectively shared between the caller and callee. If a method changes an element of an array passed as a parameter, that change will persist after the method returns.

  16. public void run() { int n = readInt("Enter number of elements: "); int[] intArray = createIndexArray(n); println("Forward: " + arrayToString(intArray)); reverseArray(intArray); println("Reverse: " + arrayToString(intArray)); } private int[] createIndexArray(int n) { int[] array = new int[n]; for ( int i = 0; i < n; i++ ) { array[i] = i; } return array; } private void reverseArray(int[] array) { for (int i = 0; i < array.length / 2; i++) { swapElements(array, i, array.length - i - 1); } } private String arrayToString(int[] array) { String str = ""; for (int i = 0; i < array.length; i++) { if (i > 0) str += ", "; str += array[i]; } return "[" + str + "]"; } private void swapElements(int[] array, int p1, int p2) { int temp = array[p1]; array[p1] = array[p2]; array[p2] = temp; } i n array n intArray 10 i array temp p1 p2 array str i array 0 9 0 9 0 0 0 1 1 1 0 8 0 2 2 2 7 6 0 3 3 3 5 0 4 4 4 5 5 4 0 5 0 6 6 3 0 7 7 2 8 1 0 8 0 0 9 9 10 10 10 10 0 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 0,1 1 9 2 3 1 9 7 3 8 6 7 5 5 6 4 2 8 4 0 ReverseArray 0,1,2 0,1,2,3 0 0 0,1,2,3,4 0,1,2,3,4,5 0,1,2,3,4,5,6 0,1,2,3,4,5,6,7 0,1,2,3,4,5,6,7,8 0,1,2,3,4,5,6,7,8,9 The ReverseArray Program public void run() { int n = readInt("Enter number of elements: "); int[] intArray = createIndexArray(n); println("Forward: " + arrayToString(intArray)); reverseArray(intArray); println("Reverse: " + arrayToString(intArray)); } n intArray 0 10 Enter number of elements: Forward: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] Reverse: [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] skip simulation

  17. Using Arrays for Tabulation • Arrays turn out to be useful when you have a set of data values and need to count how many values fall into each of a set of ranges. This process is called tabulation. • Tabulation uses arrays in a slightly different way from those applications that use them to store a list of data. When you implement a tabulation program, you use each data value to compute an index into an integer array that keeps track of how many values fall into that category. • The example of tabulation used in the text is a program that counts how many times each of the 26 letters appears in a sequence of text lines. Such a program would be very useful in solving codes and ciphers, as described on the next slide.

  18. Cryptograms • A cryptogram is a puzzle in which a message is encoded by replacing each letter in the original text with some other letter. The substitution pattern remains the same throughout the message. Your job in solving a cryptogram is to figure out this correspondence. • The usual strategy for solving a cryptogram is to assume that the most common letters in the coded message correspond to the most common letters in English, which are E, T, A, O, I, N, S, H, R, D, L, and U. • Instead of counting each of the characters by hand, it would make things easier if you had a program to do the job. You type in the coded message, and out pops a table showing how often each letter appears.

  19. 2 2 1 1 1 1 1 1 1 1 1 Implementation Strategy The basic idea behind the program to count letter frequencies is to use an array with 26 elements to keep track of how many times each letter appears. As the program reads the text, it increments the array element that corresponds to each letter. T W A S B R I L L I G 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

  20. CountLetterFrequencies import acm.program.*; /** * This program creates a table of the letter frequencies in a * paragraph of input text terminated by a blank line. */ public class CountLetterFrequencies extends ConsoleProgram { public void run() { println("This program counts letter frequencies."); println("Enter a blank line to indicate the end of the text."); initFrequencyTable(); while (true) { String line = readLine(); if (line.length() == 0) break; countLetterFrequencies(line); } printFrequencyTable(); } /* Initializes the frequency table to contain zeros */ private void initFrequencyTable() { frequencyTable = new int[26]; for (int i = 0; i < 26; i++) { frequencyTable[i] = 0; } } page 1 of 2 skip code

  21. /* Counts the letter frequencies in a line of text */ private void countLetterFrequencies(String line) { for (int i = 0; i < line.length(); i++) { char ch = line.charAt(i); if (Character.isLetter(ch)) { int index = Character.toUpperCase(ch) - 'A'; frequencyTable[index]++; } } } /* Displays the frequency table */ private void printFrequencyTable() { for (char ch = 'A'; ch <= 'Z'; ch++) { int index = ch - 'A'; println(ch + ": " + frequencyTable[index]); } } /* Private instance variables */ private int[] frequencyTable; } CountLetterFrequencies import acm.program.*; /** * This program creates a table of the letter frequencies in a * paragraph of input text terminated by a blank line. */ public class CountLetterFrequencies extends ConsoleProgram { public void run() { println("This program counts letter frequencies."); println("Enter a blank line to indicate the end of the text."); initFrequencyTable(); while (true) { String line = readLine(); if (line.length() == 0) break; countLetterFrequencies(line); } printFrequencyTable(); } /* Initializes the frequency table to contain zeros */ private void initFrequencyTable() { frequencyTable = new int[26]; for (int i = 0; i < 26; i++) { frequencyTable[i] = 0; } } page 2 of 2 skip code

  22. For example, the following declaration initializes the variable powersOfTen to the values 100, 101, 102, 103, and 104: int[] powersOfTen = {1,10,100,1000,10000}; This declaration creates an integer array of length 5 and initializes the elements as specified. Initializing Arrays • Java makes it easy to initialize the elements of an array as part of a declaration. The syntax is type[]name = { elements }; where elements is a list of the elements of the array separated by commas. The length of the array is automatically set to be the number of values in the list.

  23. As an example, suppose that you are using the integers 1 through 12 to represent the names of the months from January to December. You can easily convert these integers to the corresponding month name by declaring the following table: private static String[] MONTH_NAMES = { null /* Included because there is no month #0 */, "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; You can then use the expression MONTH_NAMES[month] to convert a numeric month to its name. Constant Lookup Tables • One of the most common applications of array initialization is to create constant arrays used to look up a value by its index number. Such arrays are called lookup tables.

  24. In Java, you can create a multidimensional array by using multiple brackets in both the type and the initialization parts of the declaration. For example, you can create array space for a 3x3 tic-tac-toe board using the following declaration: char[][] board = new char[3][3]; • This declaration creates a two-dimensional array of characters that is organized like this: board[0][0] board[0][1] board[0][2] board[1][0] board[1][1] board[1][2] board[2][0] board[2][1] board[2][2] Multidimensional Arrays • Because the elements of an array can be of any Java type, those elements can themselves be arrays. Arrays of arrays are called multidimensional arrays.

  25. For example, you can declare and initialize a multiplication table for the digits 0 to 9 like this: private static int[][] MULTIPLICATION_TABLE = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 }, { 0, 3, 6, 9, 12, 15, 18, 21, 24, 27 }, { 0, 4, 8, 12, 16, 20, 24, 28, 32, 36 }, { 0, 5, 10, 15, 20, 25, 30, 35, 40, 45 }, { 0, 6, 12, 18, 24, 30, 36, 42, 48, 56 }, { 0, 7, 14, 21, 28, 35, 42, 49, 56, 63 }, { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72 }, { 0, 9, 18, 27, 36, 45, 54, 63, 72, 81 } }; Initializing Multidimensional Arrays • You can initialize a multidimensional array when you declare it by using nested braces to reflect the levels of array nesting.

  26. Exercise: Multidimensional Arrays Write a single Java statement that declares and initializes a two-dimensional array named chessboard so that the array contains a representation of the initial position in a game of chess: The individual elements should be characters using the standard symbols for the pieces:

  27. Solution: Chessboard Problem private char[][] chessboard = { { 'r', 'n', 'b', 'q', 'k', 'b', 'n', 'r' }, { 'p', 'p', 'p', 'p', 'p', 'p', 'p', 'p' }, { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, { ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' }, { 'P', 'P', 'P', 'P', 'P', 'P', 'P', 'P' }, { 'R', 'N', 'B', 'Q', 'K', 'B', 'N', 'R' }, };

  28. Image Processing • Suppose that you have a file named JTFLogo.gif containing the logo for the ACM Java Task Force shown on the right. • As you know from the discussion of the GImage class in Chapter 9, the image actually consists of a set of pixels arranged in a two-dimensional array, as shown in the expanded image. • The GImage class allows you to convert the data for the image into a two-dimensional array of pixel values. Once you have this array, you can work with the data to change the image.

  29. For example, if you wanted to get the pixels from the image file JTFLogo.gif, you could do so with the following code: GImage logo = new GImage("JTFLogo.gif"); int[][] pixels = logo.getPixelArray(); Pixel Arrays • If you have a GImage object, you can obtain the underlying pixel array by calling the getPixelArray, which returns a two-dimensional array of type int. • The first subscript in a pixel array selects a row in the image, beginning at the top. The height of the image is therefore given by the expression pixels.length. • The second subscript in a pixel array selects an individual pixel within a row, beginning at the left. You can use the expression pixels[0].length to determine the width of the image.

  30. The next three bytes indicate the amount of red, green, and blue in the pixel, in which each value varies from 0 to 255. Together, these three bytes form the RGB value of the color, which is typically expressed using six hexadecimal digits. The color in the example has the RGB value 0x996633, which is a light brown: Pixel Values • Each individual element in a pixel array is an int in which the 32 bits are interpreted as follows: 1 1 1 1 1 1 1 1 1 0 0 1 1 0 0 1 0 1 1 0 0 1 1 0 0 0 1 1 0 0 1 1 transparency () red green blue • The first byte of the pixel value specifies the transparency of the color, which is described in more detail on the next slide.

  31. Fully transparent colors are particularly useful in images, because they make it possible to display images that do not have rectangular outlines. For example, if the gray pixels in the corners of the JTFLogo.gif image have an alpha value of 0, the background will show through those parts of the logo. Transparency • The first byte of the pixel value specifies the transparency of the color, which indicates how much of the background shows through. This value is often denoted using the Greek letter alpha (). • Transparency values vary from 0 to 255. The value 0 is used to indicate a completely transparent color in which only the background appears. The value 255 indicates an opaque color that completely obscures the background. The standard color constants all have alpha values of 255.

  32. 1. 2. 3. 4. Read an existing image from a file into a GImage object. Call getPixelArray to get the pixels. Write the code to manipulate the pixel values in the array. Call the GImage constructor to create a new image. Image Manipulation • You can use the facilities of the GImage class to manipulate images by executing the following steps: • The program on the next slide shows how you can apply this technique to flip an image vertically. The general strategy for inverting the image is simply to reverse the elements of the pixel array, using the same technique as the reverseArray method on an earlier slide.

  33. public void run() { GImage original = new GImage("Candle.gif"); GImage flipped = flipVertical(original); double y = (getHeight() - original.getHeight()) / 2; double x1 = (getWidth() - IMAGE_SEP) / 2; double x0 = x1 - original.getWidth() - IMAGE_SEP; add(original, x0, y); add(flipped, x1, y); } private GImage flipVertical(GImage image) { int[][] array = image.getPixelArray(); int height = array.length; for (int p1 = 0; p1 < height / 2; p1++) { int p2 = height - p1 - 1; int[] temp = array[p1]; array[p1] = array[p2]; array[p2] = temp; } return new GImage(array); } private GImage flipVertical(GImage image) { int[][] array = image.getPixelArray(); int height = array.length; for (int p1 = 0; p1 < height / 2; p1++) { int p2 = height - p1 - 1; int[] temp = array[p1]; array[p1] = array[p2]; array[p2] = temp; } return new GImage(array); } array array image image height height 100 The FlipVertical Program public void run() { GImage original = new GImage("Candle.gif"); GImage flipped = flipVertical(original); double y = (getHeight() - original.getHeight()) / 2; double x1 = (getWidth() - IMAGE_SEP) / 2; double x0 = x1 - original.getWidth() - IMAGE_SEP; add(original, x0, y); add(flipped, x1, y); } flipped original x0 x1 y 164 305 24 100 FlipVertical skip simulation

  34. The bitwise operators are summarized in the following table and then described in more detail on the next few slides: x & y Bitwise AND. The result has a 1 bit wherever both x and y have 1s. x | y Bitwise OR. The result has a 1 bit wherever either x or y have 1s. x ^ y Exclusive OR. The result has a 1 bit wherever x and y differ. ~x Bitwise NOT. The result has a 1 bit wherever x has a 0. x << n Left shift. Shift the bits in x left n positions, shifting in 0s. x >> n Right shift (arithmetic). Shift x right n bits, preserving the sign. x>>>n Right shift (logical). Shift x right n bits, shifting in 0s. Bitwise Operators • If you need to change the colors of individual pixels inside a pixel array, you need to learn about Java’s operators for working with individual bits in the binary representation of an integer. These operators are called the bitwise operators.

  35. For example, you can select the blue component of a pixel values by ANDing the complete value with 0xFF, as follows: 1 1 1 1 1 1 1 1 1 0 0 1 1 0 0 1 0 1 1 0 0 1 1 0 0 0 1 1 0 0 1 1 & 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 1 The Bitwise AND Operator • The bitwise AND operator (&) takes two integer operands, x and y, and computes a result that has a 1 bit in every position in which both x and y have 1 bits. A table for the & operator appears to the right. 0 1 0 0 0 1 0 1 • The primary application of the & operator is to select certain bits in an integer, clearing the unwanted bits to 0. This operation is called masking.

  36. As an example, you can use the | operator to convert an RGB value into an opaque pixel value by ORing the 24-bit RGB value with 0xFF000000, as follows: 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 1 1 0 1 0 1 1 1 1 | 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 1 1 0 1 0 1 1 1 1 The Bitwise OR Operator • The bitwise OR operator (|) takes two integer operands, x and y, and computes a result that has a 1 bit in every position in which either x or y has a 1 bit, as shown in the table on the right. 0 1 0 0 1 1 1 1 • The primary use of the | operator is to assemble a single integer value from other values, each of which contains a subset of the desired bits.

  37. As an example, you can use XOR to create a complementary color for a given RGB value by XORing it with 0xFFFFFF: 1 1 1 1 1 1 1 1 1 0 0 1 1 0 0 1 0 1 1 0 0 1 1 0 0 0 1 1 0 0 1 1 ^ 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 0 0 1 1 0 1 0 0 1 1 0 0 1 1 1 0 0 1 1 0 0 The Exclusive OR Operator • The exclusive OR or XOR operator (^) takes two integer operands, x and y, and computes a result that has a 1 bit in every position in which x and y have different bit values, as shown on the right. 0 1 0 0 1 1 1 0 • The XOR operator has many applications in programming, most of which are beyond the scope of this text. • Complementing a color twice restores the original color.

  38. For example, the expression ~0xFF creates a mask that clears the blue component of a color. The mask looks like this: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 • You can then use this mask to clear the blue byte in a color: 1 1 1 1 1 1 1 1 1 0 0 1 1 0 0 1 0 1 1 0 0 1 1 0 0 0 1 1 0 0 1 1 & 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 1 1 0 0 1 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 The Bitwise NOT Operator • The bitwise NOT operator (~) takes a single operand x and returns a value that has a 1 wherever x has a 0, and vice versa. • You can use the bitwise NOT operator to create a mask in which you mark the bits you want to eliminate as opposed to the ones you want to preserve.

  39. The Shift Operators • Java defines three operators that have the effect of shifting the bits in a word by a given number of bit positions. • The expression x <<n shifts the bits in the integer x leftward n positions. Spaces appearing on the right are filled with 0s. • The expressions x >>n and x >>>n both shift the bits in the integer x rightward n positions. The difference between the two operators lies only in the bit value shifted in as empty spaces appear on the left. • The >> operator performs what computer scientists call an arithmetic shift in which the leading bit in the value of x never changes. Thus, if the first bit is a 1, the >> operator fills spaces with 1s; if it is a 0, the spaces are filled with 0s. • The >>> operator performs a logical shift in which the spaces appearing at the left are always filled with 0s.

  40. 1 1 1 1 1 1 1 1 1 0 0 1 1 0 0 1 0 1 1 0 0 1 1 0 0 0 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 0 0 1 0 1 1 0 0 1 1 0 0 0 1 1 0 0 1 1 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 0 0 1 0 1 1 0 0 1 1 0 0 0 1 1 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 1 1 0 0 1 0 1 1 0 0 1 1 0 0 0 1 1 0 0 1 1 Exercise: Shift Operators Suppose that the integer variable pixel contains the following bit pattern, which corresponds to a light-brown color: 1. What is the value of pixel<<2? 2. What is the value of pixel>>8? 3. What is the value of pixel>>>24?

  41. 0 1 0 0 0 1 0 0 1 1 0 0 1 0 0 1 0 0 0 0 1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 0 1 1 0 0 1 1 0 1 1 1 0 1 1 0 0 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 • If the variables r, g, and b hold the individual RGB values, you can use the following expression to compute the pixel value for the corresponding opaque color: (0xFF << 24)|(r << 16)|(g << 8)| b 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 1 0 0 1 0 1 1 0 0 1 1 0 0 0 1 1 0 0 1 1 Manipulating Pixel Values • The bitwise operators make it possible to work with the components of a pixel value. For example, the expression(pixel>>16)&0xFF isolates the red component: • The GImage class exports several static methods to support this style of pixel manipulation, as shown on the next slide.

  42. Static Methods in GImage /** Returns the alpha component from an RGB value. */ public static int getAlpha(int pixel) { return (pixel >> 24) & 0xFF; } /** Returns the red component from an RGB value. */ public static int getRed(int pixel) { return (pixel >> 16) & 0xFF; } /** Returns the green component from an RGB value. */ public static int getGreen(int pixel) { return (pixel >> 8) & 0xFF; } /** Returns the blue component from an RGB value. */ public static int getBlue(int pixel) { return pixel & 0xFF; } /** Creates an opaque pixel value from the color components */ public static int createRGBPixel(int r, int g, int b) { return createRGBPixel(r, g, b, 0xFF); } /** Creates a pixel value from the color components, including alpha */ public static int createRGBPixel(int r, int g, int b, int alpha) { return (alpha << 24) | (r << 16) | (g << 8) | b; }

  43. Creating a Grayscale Image • As an illustration of how to use the bitwise operators to manipulate colors in an image, the text implements a method called createGrayscaleImage that converts a color image into a black-and-white image, as shown in the sample run at the bottom of this slide. • The code to implement this method appears on the next slide. CreateGrayscale

  44. The CreateGrayscale Program /* Creates a grayscale version of the original image */ private GImage createGrayscaleImage(GImage image) { int[][] array = image.getPixelArray(); int height = array.length; int width = array[0].length; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int pixel = array[i][j]; int r = GImage.getRed(pixel); int g = GImage.getGreen(pixel); int b = GImage.getBlue(pixel); int xx = computeLuminosity(r, g, b); array[i][j] = GImage.createRGBPixel(xx, xx, xx); } } return new GImage(array); } /* Calculates the luminosity of a pixel using the NTSC formula */ private int computeLuminosity(int r, int g, int b) { return GMath.round(0.299 * r + 0.587 * g + 0.114 * b); }

  45. The ArrayList Class • Although arrays are conceptually important as a data structure, they are not used as much in Java as they are in most other languages. The reason is that the java.util package includes a class called ArrayList that provides the standard array behavior along with other useful operations. • The main differences between Java arrays and ArrayLists stem from the fact that ArrayList is a Java class rather than a special form in the language. As a result, all operations on ArrayLists are indicated using method calls. For example, the most obvious differences include: • You create a new ArrayList by calling the ArrayList constructor. • You get the number of elements by calling the size method rather than by selecting a length field. • You use the get and set methods to select individual elements. • The next slide summarizes the most important methods in the ArrayList class. The notation <T> indicates the base type.

  46. Methods in the ArrayList Class boolean add(<T> element) Adds a new element to the end of the ArrayList; the return value is always true. void add(int index, <T> element) Inserts a new element into the ArrayList before the position specified by index. <T> remove(int index) Removes the element at the specified position and returns that value. boolean remove(<T> element) Removes the first instance of element, if it appears; returns true if a match is found. void clear() Removes all elements from the ArrayList. int size() Returns the number of elements in the ArrayList. <T> get(int index) Returns the object at the specified index. <T> set(int index, <T> value) Sets the element at the specified index to the new value and returns the old value. int indexOf(<T> value) Returns the index of the first occurrence of the specified value, or -1 if it does not appear. boolean contains(<T> value) Returns true if the ArrayList contains the specified value. boolean isEmpty() Returns true if the ArrayList contains no elements.

  47. When you declare or create an ArrayList, it is a good idea to specify the element type in angle brackets. For example, to declare and initialize an ArrayList called names that contains elements of type String, you would write ArrayList<String> names = new ArrayList<String>(); Generic Types in Java 5.0 • The <T> notation used on the preceding slide is a new feature of Java that was introduced with version 5.0 of the language. In the method descriptions, the <T> notation is a placeholder for the element type used in the array. Class definitions that include a type parameter are called generic types. • The advantage of specifying the element type is that Java now knows what type of value the ArrayList contains. When you call set, Java can ensure that the value matches the element type. When you call get, Java knows what type of value to expect, eliminating the need for a type cast.

  48. For example, suppose that you execute the following lines: ArrayList<Integer> list = new ArrayList<Integer>(); list.add(42); int answer = list.get(0); In the second statement, Java uses boxing to enclose 42 in a wrapper object of type Integer. When Java executes the third statement, it unboxes the Integer to obtain the int. Boxing and Unboxing • Generic types benefit substantially from the technique of boxing and unboxing, which was initially discussed in the slides for Chapter 7. • As of Java Standard Edition 5.0, Java automatically converts values back and forth between a primitive type and the corresponding wrapper class. This feature makes it possible to store primitive values in an ArrayList, even though the elements of any ArrayList must be a Java class.

  49. Given that older versions of Java also lack automatic boxing and unboxing, you have to perform these operations yourself: ArrayList list = new ArrayList(); list.add(new Integer(42)); int answer = ((Integer) list.get(0)).intValue(); Using ArrayList without Java 5.0 • The ArrayList class is still useful if you don’t have Java 5.0 available, although it is not nearly as convenient. • Because generic types do not exist in older versions of Java, the element type for ArrayList is defined to be Object. Although this strategy means you can store an object of any class in the ArrayList, you need to cast the result of methods like get to the desired type. • The next sets of slides show the implementation of a program to reverse a list of integers, both with and without Java 5.0.

  50. Reversing an ArrayList (Java 5.0) import acm.program.*; import java.util.*; /** * This program reads in a list of integers and then displays that list in * reverse order. This version uses an ArrayList<Integer> to hold the values. */ public class ReverseArrayList extends ConsoleProgram { public void run() { println("This program reverses the elements in an ArrayList."); println("Use " + SENTINEL + " to signal the end of the list."); ArrayList<Integer> list = readArrayList(); reverseArrayList(list); printArrayList(list); } /* Reads the data into the list */ private ArrayList<Integer> readArrayList() { ArrayList<Integer> list = new ArrayList<Integer>(); while (true) { int value = readInt(" ? "); if (value == SENTINEL) break; list.add(value); } return list; } page 1 of 2 skip code

More Related