Capitolo 7 array e array list Obiettivi del capitolo Acquisire familiarità con l utilizzo di array e array list (vettori ) Studiare le classi involucro, la tecnica di autoimpacchettamento e il ciclo for generalizzato Apprendere gli algoritmi più comuni per gli array Capire come usare array bidimensionali Imparare a scegliere array o vettori nei vostri programmi Realizzare array riempiti solo in parte Fondamenti Informatica UNIPD 2007 1 Array Array Sequenza di valori dello stesso tipo Costruisci un array: new double[10] Memorizza in variabile del tipo double[ ] double[] data = new double[10]; Quando un array viene creato, tutti i valori vengono inizializzati in base al tipo dell array: Numeri: 0 Boolean: false Riferimenti agli oggetti: null Continued Fondamenti Informatica UNIPD 2007 2 Fondamenti Informatica UNIPD 2007 3
Array Si usa [ ] per accedere ad un elemento data[2] = 29.95; DieTester.java 01: /** 02: Questo programma registra dieci lanci di un dado. 03: */ 04: public class DieTester 05: { 06: public static void main(string[] args) 07: { 08: final int TRIES = 10; 09: Die d = new Die(6); int[] lanci = new int[tries]; 10: for (int i = 0; i < TRIES; i++) { 12: lanci[i] = d.cast(); 14: 15: System.out.println(lanci); 16: 17: Fondamenti Informatica UNIPD 2007 4 Fondamenti Informatica UNIPD 2007 5 Array Array Per utilizzare il valore memorizzato: System.out.println("The data item is " + data[4]); Si ricava la lunghezza dell array con data.length. (Non è un metodo!) Il valore dell indice deve essere compreso fra 0 e length - 1 Accedere ad un elemento non esistente è un errore double[] data = new double[10]; data[10] = 29.95; // ERROR Limitazione: gli array hanno una lunghezza fissa Fondamenti Informatica UNIPD 2007 6 Fondamenti Informatica UNIPD 2007 7
Sintassi 8.1: Costruzione di Array Sintassi 8.2: Accesso a Elementi di Array new nometipo [lunghezza] Esempio: new double[10] Obiettivo: Costruire un array con un dato numero di elementi riferimentoadarray [Indice] Esempio: data[2] Obiettivo: Accedere ad un elemento diun array Fondamenti Informatica UNIPD 2007 8 Fondamenti Informatica UNIPD 2007 9 Verifica Verifica 1. Quali valori sono presenti nell array dopo l esecuzione dei seguenti enunciati? double[] data = new double[10]; for (int i = 0; i < data.length; i++) data[i] = i * i; 2. Cosa visualizzano i seguenti frammenti di programma? Oppure, se c è un errore, descrivete l errore ed indicate se si tratta di un errore di compilazione o di un errore di esecuzione. 1. double[] a = new double[10]; System.out.println(a[0]); 2. double[] b = new double[10]; System.out.println(b[10]); 3. double[] c; System.out.println(c[0]); Fondamenti Informatica UNIPD 2007 10 Fondamenti Informatica UNIPD 2007 11
Risposte Array bidimensionali 1. 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, ma non 100 2. 1. 0 2. Errore di esecuzione: indice di array fuori dai limiti 3. Errore di compilazione: c non è inizializzata Fondamenti Informatica UNIPD 2007 12 Costruendo un array bidimensionale, specificate di quante righe o colonne avete bisogno: final int ROWS = 3; final int COLUMNS = 3; String[][] board = new String[ROWS][COLUMNS]; Accedete ad elementi con una coppia di indici a[i][j] board[i][j] = "x"; Fondamenti Informatica UNIPD 2007 13 Una scacchiera Tic Tac Toe Attraversare array bidimensionali Di solito si usano cicli annidati quando si inseriscono o si cercano dati: for (int i = 0; i < ROWS; i++) for (int j = 0; j < COLUMNS; j++) board[i][j] = " "; Fondamenti Informatica UNIPD 2007 14 Fondamenti Informatica UNIPD 2007 15
File TicTacToe.java 01: /** 02: A 3 x 3 tic-tac-toe board. 03: */ 04: public class TicTacToe 05: { 06: /** 07: Constructs an empty board. 08: */ 09: public TicTacToe() 10: { 11: board = new String[ROWS][COLUMNS]; 12: // Fill with spaces 13: for (int i = 0; i < ROWS; i++) 14: for (int j = 0; j < COLUMNS; j++) 15: board[i][j] = " "; 16: 17: Segue Fondamenti Informatica UNIPD 2007 16 File TicTacToe.java 18: /** 19: Sets a field in the board. The field must be unoccupied. 20: @param i the row index 21: @param j the column index 22: @param player the player ("x" or "o") 23: */ 24: public void set(int i, int j, String player) 25: { 26: if (board[i][j].equals(" ")) 27: board[i][j] = player; 28: 29: 30: /** 31: Creates a string representation of the board, such as 32: x o 33: x 34: o 35: @return the string representation 36: */ Segue Fondamenti Informatica UNIPD 2007 17 File TicTacToe.java 37: public String tostring() 38: { 39: String r = ""; 40: for (int i = 0; i < ROWS; i++) 41: { 42: r = r + " "; 43: for (int j = 0; j < COLUMNS; j++) 44: r = r + board[i][j]; 45: r = r + " \n"; 46: 47: return r; 48: 49: 50: private String[][] board; 51: private static final int ROWS = 3; 52: private static final int COLUMNS = 3; 53: Fondamenti Informatica UNIPD 2007 18 File TicTacToeTester.java 01: import java.util.scanner; 02: 03: /** 04: This program tests the TicTacToe class by prompting the 05: user to set positions on the board and printing out the 06: result. 07: */ 08: public class TicTacToeTester 09: { 10: public static void main(string[] args) 11: { 12: Scanner in = new Scanner(System.in); 13: String player = "x"; 14: TicTacToe game = new TicTacToe(); 15: boolean done = false; 16: while (!done) 17: { Segue Fondamenti Informatica UNIPD 2007 19
File TicTacToeTester.java 18: System.out.print(game.toString()); 19: System.out.print( 20: "Row for " + player + " (-1 to exit): "); 21: int row = in.nextint(); 22: if (row < 0) done = true; 23: else 24: { 25: System.out.print("Column for " + player + ": "); 26: int column = in.nextint(); 27: game.set(row, column, player); 28: if (player.equals("x")) 29: player = "o"; 30: else 31: player = "x"; 32: 33: 34: 35: Segue Fondamenti Informatica UNIPD 2007 20 Output Row for x (-1 to exit): 1 Column for x: 2 x Row for o (-1 to exit): 0 Column for o: 0 o x Row for x (-1 to exit): -1 Fondamenti Informatica UNIPD 2007 21 Verifica Risposte 11. Come si dichiara e si inizializza un array di interi 4 per 4? 12. Come si conta il numero di caselle non occupate nella scacchiera tic-tac-toe? 11. 12. int[][] array = new int[4][4]; int count = 0; for (int i = 0; i < ROWS; i++) for (int j = 0; j < COLUMNS; j++) if (board[i][j] == ' ') count++; Fondamenti Informatica UNIPD 2007 22 Fondamenti Informatica UNIPD 2007 23
Copiare Array: Copiare riferimenti agli array Copiare Array: Copiare riferimenti agli array Copiando una variabile array otterrete un altro riferimento allo stesso array double[] data = new double[10]; // fill array... double[] prices = data; Segue Fondamenti Informatica UNIPD 2007 24 Fondamenti Informatica UNIPD 2007 25 Copiare = Clonare array Copiare = Clonare array Usate clone per fare una vera copia double[] prices = (double[]) data.clone(); Segue Fondamenti Informatica UNIPD 2007 26 Fondamenti Informatica UNIPD 2007 27
Copiare Array: Copiare elementi array Aggiungere un elemento ad un array System.arraycopy(from, fromstart, to, tostart, count); System.arraycopy(data, i, data, i + 1, data.length - i - 1); data[i] = x; Fondamenti Informatica UNIPD 2007 28 Fondamenti Informatica UNIPD 2007 29 Rimuovere un elemento da un array Ingrandire un array System.arraycopy(data, i + 1, data, i, data.length - i - 1); Se l array è pieno e avete bisogno di più spazio, potete ingrandirlo: 1. Creare un nuovo array più grande. double[] newdata = new double[2 * data.length]; 2. Copiare tutti gli elementi nel nuovo array System.arraycopy(data, 0, newdata, 0, data.length); 3. Salvare il riferimento al nuovo array nella variabile array data = newdata; Fondamenti Informatica UNIPD 2007 30 Fondamenti Informatica UNIPD 2007 31
Ingrandire un array Verifica 13. Come si aggiungono o si eliminano elementi in una posizione intermedia di un vettore? 14. Perché, quando non c è più spazio in un array, ne raddoppiamo la dimensione invece di aumentarla di un unità? Fondamenti Informatica UNIPD 2007 32 Fondamenti Informatica UNIPD 2007 33 Risposte Trasformare array paralleli in array di oggetti 13. Usate I metodi insert e remove. 14. Perché è uno spreco di tempo, bisognerebbe ripetere il processo ogni volta che si aggiunge un elemento. // Don't do this int[] accountnumbers; double[] balances; Fondamenti Informatica UNIPD 2007 34 Fondamenti Informatica UNIPD 2007 35
Trasformare array paralleli in array di oggetti Evitate array paralleli array di oggetti: BankAccount[] = accounts; Fondamenti Informatica UNIPD 2007 36 Array riempiti solo in parte Lunghezza di un array = numero massimo di elementi in un array Di solito è riempito solo in parte Necessita di una variabile associata per tenere traccia della dimensione corrente Uniformate I nomi: final int DATA_LENGTH = 100; double[] data = new double[data_length]; int datasize = 0; Segue Fondamenti Informatica UNIPD 2007 37 Array riempiti solo in parte Array riempiti solo in parte Aggiornate datasize quando l array è pieno: data[datasize] = x; datasize++; Fondamenti Informatica UNIPD 2007 38 Fondamenti Informatica UNIPD 2007 39
Buffer over-run Vettori La classe ArrayList controlla una serie di oggetti Può crescere e restringersi in base alle necessità La classe ArrayList fornisce metodi per svolgere le operazioni più comuni, come l inserimento o la rimozione di elementi Continued Fondamenti Informatica UNIPD 2007 40 Fondamenti Informatica UNIPD 2007 41 Vettori Ricavare elementi di un vettore La classe ArrayList è una classe generica: ArrayList<T> contiene oggetti del tipo T: ArrayList<BankAccount> accounts = new ArrayList<BankAccount>(); accounts.add(new BankAccount(1001)); accounts.add(new BankAccount(1015)); accounts.add(new BankAccount(1022)); Si usa il metodo get L indice parte da 0 BankAccount anaccount = accounts.get(2); // ricava il terzo elemento di un vettore Se l indice è fuori dai valori, risulta un errore di limiti Il metodo size restituisce la dimensione attuale di un vettore Fondamenti Informatica UNIPD 2007 42 Fondamenti Informatica UNIPD 2007 43
Ricavare elementi di un vettore Errori di limiti più comuni: int i = accounts.size(); anaccount = accounts.get(i); // Error // legal index values are 0...i-1 Fondamenti Informatica UNIPD 2007 44 Aggiungere e rimuovere elementi set sovrascrive un elemento esistente BankAccount anaccount = new BankAccount(1729); accounts.set(2, anaccount); add aggiunge un nuovo valore nella posizione indicata accounts.add(i, a) remove rimuove l elemento nella posizione indicata Accounts.remove(i) Continued Fondamenti Informatica UNIPD 2007 45 Aggiungere e rimuovere elementi File: ArrayListTester.java 01: import java.util.arraylist; 02: 03: /** 04: This program tests the ArrayList class. 05: */ 06: public class ArrayListTester 07: { 08: public static void main(string[] args) 09: { 10: ArrayList<BankAccount> accounts 11: = new ArrayList<BankAccount>(); 12: accounts.add(new BankAccount(1001)); 13: accounts.add(new BankAccount(1015)); 14: accounts.add(new BankAccount(1729)); 15: accounts.add(1, new BankAccount(1008)); 16: accounts.remove(0); jcreator Fondamenti Informatica UNIPD 2007 46 Fondamenti Informatica UNIPD 2007 47
File: ArrayListTester.java 17: 18: System.out.println("size=" + accounts.size()); 19: BankAccount first = accounts.get(0); 20: System.out.println("first account number=" 21: + first.getaccountnumber()); 22: BankAccount last = accounts.get(accounts.size() - 1); 23: System.out.println("last account number=" 24: + last.getaccountnumber()); 25: 26: File: BankAccount.java 01: /** 02: A bank account has a balance that can be changed by 03: deposits and withdrawals. 04: */ 05: public class BankAccount 06: { 07: /** 08: Constructs a bank account with a zero balance 09: @param anaccountnumber the account number for this account 10: */ 11: public BankAccount(int anaccountnumber) 12: { 13: accountnumber = anaccountnumber; 14: balance = 0; 15: 16: Fondamenti Informatica UNIPD 2007 48 Fondamenti Informatica UNIPD 2007 49 File: BankAccount.java 17: /** 18: Constructs a bank account with a given balance 19: @param anaccountnumber the account number for this account 20: @param initialbalance the initial balance 21: */ 22: public BankAccount(int anaccountnumber, double initialbalance) 23: { 24: accountnumber = anaccountnumber; 25: balance = initialbalance; 26: 27: 28: /** 29: Gets the account number of this bank account. 30: @return the account number 31: */ 32: public int getaccountnumber() 33: { 34: return accountnumber; 35: Continued Fondamenti Informatica UNIPD 2007 50 File: BankAccount.java 36: 37: /** 38: Deposits money into the bank account. 39: @param amount the amount to deposit 40: */ 41: public void deposit(double amount) 42: { 43: double newbalance = balance + amount; 44: balance = newbalance; 45: 46: 47: /** 48: Withdraws money from the bank account. 49: @param amount the amount to withdraw 50: */ 51: public void withdraw(double amount) 52: { 53: double newbalance = balance - amount; 54: balance = newbalance; Continued Fondamenti Informatica UNIPD 2007 51
File: BankAccount.java 55: 56: 57: /** 58: Gets the current balance of the bank account. 59: @return the current balance 60: */ 61: public double getbalance() 62: { 63: return balance; 64: 65: 66: private int accountnumber; 67: private double balance; 68: Output size=3 first account number=1008 last account number=1729 Fondamenti Informatica UNIPD 2007 52 Verifica 3. Come si costruisce un array di 10 stringhe? E un vettore di stringhe? 4. Cosa contiene names dopo l esecuzione dei seguenti enunciati? ArrayList<String> names = new ArrayList<String>(); names.add("a"); names.add(0, "B"); names.add("c"); names.remove(1); Fondamenti Informatica UNIPD 2007 53 Risposte Involucri 3. new String[10]; new ArrayList<String>(); 4. names contiene le stringhe "B" e "C" alle posizioni 0 e 1 Non si possono inserire tipi primitivi direttamente in vettori, devono essere trasformati in oggetti classi involucro ArrayList<Double> data = new ArrayList<Double>(); data.add(29.95); double x = data.get(0); Fondamenti Informatica UNIPD 2007 54 Fondamenti Informatica UNIPD 2007 55
Involucri Auto-impacchettamento classi involucro per tutti i tipi primitivi Auto-impacchettamento: a partire da Java 5.0, la conversione tra tipi primitivi e le corrispondenti classi involucro è automatica Double d = 29.95; // auto-boxing; same as // Double d = new Double(29.95); double x = d; // auto-unboxing; same as // double x = d.doublevalue(); Fondamenti Informatica UNIPD 2007 56 Fondamenti Informatica UNIPD 2007 57 Auto-impacchettamento L auto-impacchettamento lavora anche all interno di espressioni aritmetiche Double e = d + 1; Significati: Converti d in un valore di tipo double Aggiungi 1 Impacchetta il risultato in un nuovo oggetto di tipo Double Memorizza in e il riferimento all oggetto involucro appena creato Fondamenti Informatica UNIPD 2007 58 Verifica 5. Qual è la differenza fra i tipi double e Double? 6. Se data è un esemplare di ArrayList<Double> con dimensione maggiore di zero, come si aggiunge un unità al valore memorizzato nell elemento di indice zero? Fondamenti Informatica UNIPD 2007 59
Risposte Il ciclo for generalizzato 5. double è uno degli otto tipi primitivi. Double è un tipo di classe. 6. data.set(0, data.get(0) + 1); double[] data =...; double sum = 0; for (double e : data) { sum = sum + e; double[] data =...; double sum = 0; for (int i = 0; i < data.length; i++) { double e = data[i]; sum = sum + e; Fondamenti Informatica UNIPD 2007 60 Fondamenti Informatica UNIPD 2007 61 Il ciclo for generalizzato Il ciclo for generalizzato Funziona anche per ArrayLists : ArrayList<BankAccount> accounts =... ; double sum = 0; for (BankAccount a : accounts) { sum = sum + a.getbalance(); E equivalente al seguente ciclo for ordinario: double sum = 0; for (int i = 0; i < accounts.size(); i++) { BankAccount a = accounts.get(i); sum = sum + a.getbalance(); Fondamenti Informatica UNIPD 2007 62 Fondamenti Informatica UNIPD 2007 63
Sintassi 8.3: Il ciclo for generalizzato Verifica for (Type variable : collection) statement Esempio: for (double e : data) sum = sum + e; Obiettivo: Eseguire un ciclo avente un iterazione per ogni elemento appartenente ad una raccolta. All inizio di ciascuna iterazione viene assegnato alla variabile l elemento successivo della raccolta, poi viene eseguito l enunciato. 7. Scrivi un ciclo for generalizzato che visualizzi tutti gli elementi dell array data 8. Perchè non è ragionevole utilizzare un ciclo for generalizzato al posto del seguente ciclo ordinario? for (int i = 0; i < data.length; i++) data[i] = i * i; Fondamenti Informatica UNIPD 2007 64 Fondamenti Informatica UNIPD 2007 65 7. Risposte for (double x : data) System.out.println(x); 8. Il ciclo scrive un valore data[i]. Il ciclo for non ha l indice variabile i. Fondamenti Informatica UNIPD 2007 66 Semplici algoritmi per vettori: contare occorrenze di un valore Controlla tutti gli elementi e conta le occorrenze di un valore fino alla fine dell array public class Bank { public int count(double atleast) { int matches = 0; for (BankAccount a : accounts) { if (a.getbalance() >= atleast) matches++; // Found a match return matches;... private ArrayList<BankAccount> accounts; Fondamenti Informatica UNIPD 2007 67
Semplici algoritmi per vettori: Trovare un valore Semplici algoritmi per vettori : Trovare il massimo o il minimo Controllate tutti gli elementi finché trovate un valore. public class Bank { public BankAccount find(int accountnumber){ for (BankAccount a : accounts) { // Found a match if (a.getaccountnumber() == accountnumber) return a; return null; // No match in the entire array list private ArrayList<BankAccount> accounts; Fondamenti Informatica UNIPD 2007 68 Scegliete un candidato come valore massimo Confrontate il candidato con gli altri elementi Sostituitelo se trovate un valore maggiore o minore Segue Fondamenti Informatica UNIPD 2007 69 Semplici algoritmi per vettori : Trovare il massimo o il minimo Semplici algoritmi per vettori : Trovare il massimo o il minimo Esempio: BankAccount largestyet = accounts.get(0); for (int i = 1; i < accounts.size(); i++) { BankAccount a = accounts.get(i); if (a.getbalance() > largestyet.getbalance()) largestyet = a; return largestyet; Funziona solo se c è almeno un elemento nella lista degli array Se la lista è vuota, il metodo restituisce null if (accounts.size() == 0) return null; BankAccount largestyet = accounts.get(0);... Fondamenti Informatica UNIPD 2007 70 Fondamenti Informatica UNIPD 2007 71
File Bank.java 01: import java.util.arraylist; 02: 03: /** 04: This bank contains a collection of bank accounts. 05: */ 06: public class Bank 07: { 08: /** 09: Constructs a bank with no bank accounts. 10: */ 11: public Bank() 12: { 13: accounts = new ArrayList<BankAccount>(); 14: 15: 16: /** 17: Adds an account to this bank. jcreator 18: @param a the account to add 19: */ Segue Fondamenti Informatica UNIPD 2007 72 File Bank.java 20: public void addaccount(bankaccount a) 21: { 22: accounts.add(a); 23: 24: 25: /** 26: Gets the sum of the balances of all accounts in this bank. 27: @return the sum of the balances 28: */ 29: public double gettotalbalance() 30: { 31: double total = 0; 32: for (BankAccount a : accounts) 33: { 34: total = total + a.getbalance(); 35: 36: return total; 37: 38: Segue Fondamenti Informatica UNIPD 2007 73 File Bank.java File Bank.java 39: /** 40: Counts the number of bank accounts whose balance is at 41: least a given value. 42: @param atleast the balance required to count an account 43: @return the number of accounts having least the given // balance 44: */ 45: public int count(double atleast) 46: { 47: int matches = 0; 48: for (BankAccount a : accounts) 49: { 50: if (a.getbalance() >= atleast) matches++; // Found // a match 51: 52: return matches; 53: Segue 54: Fondamenti Informatica UNIPD 2007 74 55: /** 56: Finds a bank account with a given number. 57: @param accountnumber the number to find 58: @return the account with the given number, or null 59: if there is no such account 60: */ 61: public BankAccount find(int accountnumber) 62: { 63: for (BankAccount a : accounts) 64: { 65: if (a.getaccountnumber() == accountnumber) // Found a match 66: return a; 67: 68: return null; // No match in the entire array list 69: 70: Segue Fondamenti Informatica UNIPD 2007 75
File Bank.java 71: /** 72: Gets the bank account with the largest balance. 73: @return the account with the largest balance, or 74: null if the bank has no accounts 75: */ 76: public BankAccount getmaximum() 77: { 78: if (accounts.size() == 0) return null; 79: BankAccount largestyet = accounts.get(0); : for (int i = 1; i < accounts.size(); i++) 81: { 82: BankAccount a = accounts.get(i); 83: if (a.getbalance() > largestyet.getbalance()) 84: largestyet = a; 85: 86: return largestyet; 87: 88: 89: Fondamenti private ArrayList<BankAccount> accounts; Informatica UNIPD 2007 76 90: File BankTester.java 01: /** 02: This program tests the Bank class. 03: */ 04: public class BankTester 05: { 06: public static void main(string[] args) 07: { 08: Bank firstbankofjava = new Bank(); 09: firstbankofjava.addaccount(new BankAccount(1001, 20000)); 10: firstbankofjava.addaccount(new BankAccount(1015, 10000)); 11: firstbankofjava.addaccount(new BankAccount(1729, 15000)); 12: 13: double threshold = 15000; 14: int c = firstbankofjava.count(threshold); 15: System.out.println(c + " accounts with balance >= " + threshold); Segue Fondamenti Informatica UNIPD 2007 77 File BankTester.java File BankTester.java 16: 17: int accountnumber = 1015; 18: BankAccount a = firstbankofjava.find(accountnumber); 19: if (a == null) 20: System.out.println("No account with number " + accountnumber); 21: else 22: System.out.println("Account with number " + accountnumber 23: + " has balance " + a.getbalance()); 24: 25: BankAccount max = firstbankofjava.getmaximum(); 26: System.out.println("Account with number " 27: + max.getaccountnumber() 28: + " has the largest balance."); 29: 30: Segue Fondamenti Informatica UNIPD 2007 78 Output 2 accounts with balance >= 15000.0 Account with number 1015 has balance 10000.0 Account with number 1001 has the largest balance. Fondamenti Informatica UNIPD 2007 79
Verifica Risposte 9. Come si comporta il metodo find se esistono due conti bancari con il numero di conto uguale al numero cercato? 10. Si potrebbe usare il ciclo "for" generalizzato nel metodo getmaximum? 9. Restituisce il primo che trova 10. Sì, ma il primo confronto fallirà sempre Fondamenti Informatica UNIPD 2007 Fondamenti Informatica UNIPD 2007 81