Array augmentation problem in Java
I have here a program that is supposed to begin with an array of length 1, allow the user to make an entry into the array, and then double the size of the array with each entry the user makes to avoid an java.lang.ArrayIndexOutOfBoundsException error. The way the code is written below, the computer skips else if after the second user entry and goes straight for Sorry, database is full. If I add newRecords = records in the first else if block, I get the java.lang.ArrayIndexOutOfBoundsException error.
public class PhoneDirectory5 {
public static void main(String args[]) {
**PhoneRecord[] records= new PhoneRecord[1];
int numRecords = 0;**
// Display list of commands
System.out.println("Phone directory commands: \n" +
" a - Add a new phone number\n" +
" f - Find a new phone number\n" +
" q - Quit\n" +
" d - Delete record\n");
// Read and execute commands
while (true) {
// Prompt user to enter a command
SimpleIO.prompt("Enter command (a, f, d, or q): ");
String command = SimpleIO.readLine().trim();
// Determine whether command is "a", "f", "q", or
// illegal. Execute command if illegal.
**if (command.equalsIgnoreCase("a"))** {
// Command is "a". prompt user for name and number,
// then create a phone record and store it in the
// database.
**if (numRecords < records.length) {
SimpleIO.prompt("Enter a new name: ");
String name = SimpleIO.readLine().trim();
SimpleIO.prompt("Enter new phone number: ");
String number = SimpleIO.readLine().trim();
records[numRecords] =
new PhoneRecord(name, number);
numRecords++;
} else if (numRecords == records.length) {
PhoneRecord[] newRecords = new PhoneRecord[records.length*2];
System.arraycopy(records, 0, newRecords, 0, records.length);
SimpleIO.prompt("Enter a new name: ");
String name = SimpleIO.readLine().trim();
SimpleIO.prompt("Enter new phone number: ");
String number = SimpleIO.readLine().trim();
newRecords[numRecords] =
new PhoneRecord(name, number);
numRecords++;**
} else
System.out.println("Sorry, database is full.");
} else if (command.equalsIgnoreCase("f")) {
// Command is "f". Prompt user for search key.
// Search the database for records whose name begins
// with the search key. Print these names and the
// corresponding phone numbers.
SimpleIO.prompt("Enter name to look up: ");
String key = SimpleIO.readLine().trim().toLowerCase();
for (int i = 0; i < numRecords; i++) {
String name = records[i].getName().toLowerCase();
if (name.startsWith(key)) {
System.out.println(records[i].getName() + " " +
records[i].getNumber());
break;
} else if (i == numRecords - 1)
System.out.println("Sorry, your search did not" +
" match any records.");
}
} else if (command.equalsIgnoreCase("d")) {
SimpleIO.prompt("Enter the name of the record to delete: ");
String key = SimpleIO.readLine().trim().toLowerCase();
for (int i = 0; i < numRecords; i++) {
String name = records[i].getName().toLowerCase();
if (name.startsWith(key)) {
records[i] = new PhoneRecord("", "");
break;
} else if (i == numRecords - 1)
System.out.println("Sorry, your search did not match" +
" any records.");
}
} else if (command.equalsIgnoreCase("q")) {
// Command is "q".. Terminate program
System.out.println("You have elected to exit the phone directory.");
return;
} else {
// Command is illegal. Display error message.
System.out.println("Command was not recognized; " +
"please enter only a, f, d or q.");
}
System.out.println();
}
}
}
// Represents a record containing a name and a phone number
class PhoneRecord {
private String name;
private String number;
// Constructor
public PhoneRecord(String personName, String phoneNumber) {
name = personName;
number = phoneNumber;
}
// Returns the name stored in the record
public String getName() {
retur开发者_运维问答n name;
}
// Returns the phone number stored in the record
public String getNumber() {
return number;
}
}
All this being said, when I allocated new array space in this fashion...
else if (numRecords == records.length) {
PhoneRecord[] newRecords = new PhoneRecord[records.length*2];
for (int i = 0; i < records.length; i++)
newRecords[i] = records[i];
records = newRecords;
SimpleIO.prompt("Enter a new name: ");
String name = SimpleIO.readLine().trim();
SimpleIO.prompt("Enter new phone number: ");
String number = SimpleIO.readLine().trim();
newRecords[numRecords] =
new PhoneRecord(name, number);
numRecords++;
...the program did exactly what I needed it to do, namely, double the size of the array with each user entry and never print the "Sorry, but the database is full" message. My question is, why can't I get the program to work with the .arraycopy method? Any help would be much appreciated.
When I do this...
else if (numRecords == records.length) {
PhoneRecord[] newRecords = new PhoneRecord[records.length*2];
System.arraycopy(records, 0, newRecords, 0, records.length);
**newRecords = records;**
SimpleIO.prompt("Enter a new name: ");
String name = SimpleIO.readLine().trim();
SimpleIO.prompt("Enter new phone number: ");
String number = SimpleIO.readLine().trim();
newRecords[numRecords] =
new PhoneRecord(name, number);
numRecords++;
...is when I get the arrayindexoutofbounds error.
Arrays have a fixed length in Java. If you want a dynamic-length array, rather than programming it from scratch, you should use the one given for you in the standard API : java.util.ArrayList. Look at its documentation here : http://download.oracle.com/javase/6/docs/api/java/util/ArrayList.html. This class is part of the Java collections API, which is a must-know for any Java programmer. Learn to use them in the Java tutorial.
Rather than a PhoneRecord[]
, you would have a list of PhoneRecord
s :
List<PhoneRecord> records = new ArrayList<PhoneRecord>();
You can add a new record with
records.add(newRecord);
and the array wrapped by the array list will automatically grow if needed.
And you can access to a specific index with
PhoneRecord record = records.get(index);
You can also iterate on the list as you would with an array :
for (PhoneRecord record : records) {
// ...
}
You didn't assign newRecords back to records in the System.arraycopy example.
edit: I agree with JB Nizet. You should use ArrayList instead.
It seems to me the easiest way to get around this is creating a try/catch for the exception. When exception comes in you create the new array. if you cant get the arraycopy to work you can always make a loop to copy elements from old array to new one.
精彩评论