Problem copying an arraylist to an array
So I have a specific requirement that a list be stored as an array, but the professor suggested it would be easier to start it off as an arraylist then use the .toArray method to copy it to a new array. The thing is, the array is to be declared as a field as "songs", and at that point the program won't know how many objects are going to be in the list, and the number of songs is an important part for later sections of the program.
Basically what's happening is I'm supposed to take a text file with around 10,000 song lyrics and organize them so they'll be searchable. The text file is organized well, so I just read through the file and make each one a Song object, with String parameters containing title, artist, and lyrics. As they're read in, I add them to an arrayList, songsAL. After all that is done, I try to copy songsAL to the existing (but uninitialized) array songs, and I get a nullpointerexception. If I just keep it as an arrayList and change any place is requires an array to an arraylist, it works fine. But he gave us a GUI we're supposed to use it with, and I doubt that will work if I keep it as an arrayList.
It's been over a year since I've done any programming work, and before that I had only done it for a year, so I'm pretty rusty. The existing comments were meant for the professor, but they might help you understand my thinking.
Here's my code:
Code :
import java.io.*;
import java.util.*;
/*
* SongCollection.java
* Read the specified data file and build an array of songs.
*
* Initial code by Bob Boothe September 2008
*/
public class CopyOfSongCollection {
private Song[] songs; /*I can't figure out a way to copy the ArrayList I have to
the existing array songs. I could make a new array inside the
constructor, but then I wouldn't be able to access it. I tried
actually building the array during the file scanning process,
but without initializing it first I can't. The only way I can
think of would be to initialize it up here, but that would make
it a lot harder to get the number of songs, since I would have to
initialize it before knowing the number of songs in the text file.
*/
private ArrayList<Song> songsAL = new ArrayList<Song>();
//so I just used an arrayList for the whole thing
public CopyOfSongCollection(String filename) throws IOException {
//read in the file and build songs array
try{
FileReader reader = new FileReader(filename);
Scanner fileScan = new Scanner(reader);
while(fileScan.hasNext()){ //as long as there is something in the next spot of the file
String a = fileScan.nextLine();//first line will be artist
a = a.substring(8, a.length()-1);//remove prefix 'ARTIST="'
String t = fileScan.nextLine();//next line is title of song
t = t.substring(7, t.length()-1);//again, remove prefix
String l =""; //initialize string for lyrics
while(!fileScan.hasNext("\"")){//while the next character is NOT a double quote
l = l + "\n" + fileScan.nextLine();//add the next line to the lyrics string
}
l = l.substring(9, l.length()); //remove prefix
fileScan.nextLine(); //necessary to skip the line with just quotations
Song s = new Song(a, t, l); //build song object out of previously obtained info
this.songsAL.add(s); //add song object to arraylist
}
}catch (FileNotFoundException e){
System.err.println("File not found");
System.exit(1);
}
// sort the songs array
Collections.sort(songsAL);
for(int i = 0; i < songsAL.size(); i++){
songs[i] = songsAL.get(i);
}
// print statistics:
System.out.println("Number of songs: " + songsAL.size());// the number of songs
System.out.println("Number of comparisons used: " + Song.getCount());// the number of comparisons used to sort it
}
// return the songs array
// this is used as the data source for building other data structures
public Song[] getAllSongs() {
return songs;
//I'm assuming this is where the importance of using an array instead of
//an arraylist comes into play. I just changed it to an arraylist.
}
// testing method
public static void main(String[] args) throws IOException {
// todo: show First 10 songs
CopyOfSongCollection sc = new CopyOfSongCollection("allSongs.txt");
try{
for(int i = 0; i < 10; i++){
System.out.println("Artist:" + sc.songsAL.get(i).getArtist());
System.out.println("Title: " + sc.songsAL.get(i).getTitle());
}
}catch (IndexOutOfBoundsException e){
System.err.println("Array doesn't have that index!");
}
if (args.length == 0) { //not entirely sure what this code is for
System.err.println("usage: prog songfile");
return;
}
}
}
Re: Problem copying an arraylist to an array
Code :
songs[i] = songsAL.get(i);
NPE thrown here, right? songs[i] should choose a Song reference from your array of Song references call 'songs' declared:
What is the value of the reference 'songs'? Do you assign it anywhere? You could fix your code by answering this question. Alternatively:
ArrayList extends AbstractCollection, which has a handy method whose return type is an array of all the elements in the AbstractCollection. See if you can spot which one it is.
Re: Problem copying an arraylist to an array
There is no value of 'songs' yet. I want songs to be identical to songsAL, except for it to be an array and not an arrayList. I can't declare it because I don't know what the size of the array is going to be at that point.
Re: Problem copying an arraylist to an array
You could create the songs array and assign it as soon as you finish loading your ArrayList. You know what size the array has to be at that point: the same size as the ArrayList. That's if you want to create it and assign the elements one-by-one rather than using the handy method in AbstractCollection.
Re: Problem copying an arraylist to an array
I get it now. Dumb mistake, I didn't realize I could assign a size to the array songs after I had already declared it as a field. Thanks for your help.