I just got back from a programming competition. I'm very frustrated because I wrote what seems to be correct code for one of the problems, but I'm getting very strange results. After the competition I showed the code to several people and no one could figure out what's wrong with it. I'd like to know if it's a bug in Java 1.4.2_05 or my fault. Here's the problem:
You are given a file with a list of names of songs in it. For each song you find, you must increment it's popularity, it is also case insensitive. So if you find "oh yeah" and "oH YEah", that song has a popularity of 2. Finally you must display the top five most popular songs.
Here is the input file (songs.in):
Code:
ACM ROX
syzygy
123
thisisasong5
myfavoritesong
ACM ROX
SYZYGY
123
thisisasong5
ACM ROX
sYzYgY
123
Acm Rox
syzygy
ACM ROx
And here is my code:
[php]import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.Comparator;
import java.util.TreeSet;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.FileReader;
import java.io.File;
public class Songs {
private static final String file = "songs.in";
TreeSet songs;
public static void main(String[] args) {
new Songs();
}
public Songs() {
songs = new TreeSet(new CompareSongs());
try {
BufferedReader in = new BufferedReader(new FileReader(file));
String aSong;
int asdf = 0; // just for debugging; ignore this variable
while ((aSong = in.readLine()) != null) {
asdf++;
Iterator i = songs.iterator();
boolean foundSong = false;
while (i.hasNext()) {
Song song = (Song)i.next();
System.out.println("Loop "+asdf+": "+song.name);
if (song.name.equalsIgnoreCase(aSong)) {
System.out.println("already have "+song.name);
song.popularity++;
foundSong = true;
}
}
if (foundSong == false) {
Song song1 = new Song(aSong);
song1.popularity++;
songs.add(song1);
System.out.println("Added song "+aSong);
}
}
try {
for (int i=0; i<5; i++) {
Song song2 = (Song)songs.last();
System.out.println(song2.name + " "+song2.popularity);
songs.remove(song2);
}
} catch (NoSuchElementException e) {
System.out.println("finish");
}
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
}
}
private class CompareSongs implements Comparator {
public int compare(Object o1, Object o2) {
if (((Song)o1).popularity > ((Song)o2).popularity) {
return 1;
} else if (((Song)o1).popularity < ((Song)o2).popularity) {
return -1;
} else {
return 0;
}
}
}
private class Song {
public int popularity=0;
public String name;
public Song(String name) {
popularity = 0;
this.name = name;
}
public boolean equals(Object o) {
if (this.name.equalsIgnoreCase(((Song)o).name))
return true;
else
return false;
}
}
}[/php]
The result from running this code is describe as follows: At first it will add the song to the TreeSet correctly, and the next time around it'll correctly show that there is one Song in the TreeSet. However, as more songs are added, the amount of songs returned by the Iterator remains only 1. It then says for a while that there are only two songs (when there should be a lot more), and sometimes it will actually
decrease in the amount of Songs returned! (It will iterate through 3 songs, and then drop down to 1 song in the next loop around).
Any help figuring out what's going on is greatly appreciated!