将arraylist打印成输出文件?

时间:2014-03-23 02:11:46

标签: java sorting arraylist filter comparator

这里的问题:Java: Printing Arraylist to Output File?

出于某种原因,ArrayLists需要花费大量时间才能打印到输出文件,通常需要20-30分钟。但是,这仅适用于排序方法或filterTitlefilterArtist方法(涉及字符串输入的方法)。 当我运行filterRankfilterYear时,它运行得很好。

当我直接从过滤方法打印song2 ArrayList时,打印的唯一内容是[],这意味着ArrayList为空,但它不应该是?无论如何,filterRankfilterYear方法仍然有效。 但不知何故,我认为这是相关的。

输入文件可在此处找到:http://staff.rentonschools.us/hhs/ap-comp-science/projects/download/agazillionsongs.txt?id=223098

示例排序方法:

public void sortYear() {
   Collections.sort(songs2, SongComparator.byYear()); // now we have a sorted list
   System.out.println(songs2);
}

示例过滤方法(用于字符串)

public void filterArtist(String s) {
   int n = 0;
   if (n == 0) {
      System.out.println("Program is processing.");
      n++;
      for (Song song1 : songs2) {
         if ((!(((song1.artist).contains(s))))) {
            itemsToRemove.add(song1);
         }
      }
      songs2.removeAll(itemsToRemove);
      itemsToRemove.clear();
   }
   System.out.println(songs2);
}

示例过滤方法(用于整数)

public void filterRank(Range r) {
   int n = 0;
   if (n == 0) {
      System.out.println("Program is processing.");
      n++;
      for (Song song1 : songs2) {
         if (song1.rank > (r.getMax()) || (song1.rank) < (r.getMin())) {
            itemsToRemove.add(song1);
         }
      }
      songs2.removeAll(itemsToRemove);
      itemsToRemove.clear();
   }
   System.out.println(songs2);
}

打印/输出文件的主类中的代码

while (input.hasNextLine()) {
   int n = 0;
   SongCollection collection = new SongCollection(songs);
   String inputType = input.nextLine();
   String delims = "[ ]";
   String[] tokens = inputType.split(delims);
   for (int i = 0; i < tokens.length; i++) {
      n = 0;
      if (n == 0) {
         if ((tokens[i]).contains("year:")) {
            collection.filterYear(Range.parse(tokens[i]));
            n = 1;
         }// end of year loop
         if ((tokens[i]).contains("rank:")) {
            collection.filterRank(Range.parse(tokens[i]));
            n = 1;
         }// end of rank
         if ((tokens[i]).contains("artist:")) {
            collection.filterArtist(tokens[i]);
            n = 1;
         }// end of artist
         if ((tokens[i]).contains("title:")) {
            collection.filterTitle(tokens[i]);
            n = 1;
         }// end of title
         if ((tokens[i]).contains("sort:")) {
               if ((tokens[i]).contains("title")) {
                  collection.sortTitle();
                  n = 1;
               }// end of sort title
               if ((tokens[i]).contains("artist")) {
                  collection.sortArtist();
                  n = 1;
               }// end of sort artist
               if ((tokens[i]).contains("rank")) {
                  collection.sortRank();
                  n = 1;
               }// end of sort rank
               if ((tokens[i]).contains("year")) {
                  collection.sortYear();
                  n = 1;
               }// end of sort year
         }//end of sort
      }// end of for loop

   }// end of input.hasNextline loop
   final PrintStream console = System.out; //saves original System.out
   File outputFile = new File("output.txt"); //output file
   PrintStream out = new PrintStream(new FileOutputStream(outputFile)); //new FileOutputStream
   System.setOut(out); //changes where data will be printed
   System.out.println(collection.toString());

   System.setOut(console); //changes output to print back to console
   Scanner outputFileScanner = new Scanner(outputFile); //inputs data from file
   while ((outputFileScanner.hasNextLine())) { //while the file still has data
      System.out.println(outputFileScanner.nextLine()); //print
   }
   outputFileScanner.close();
   out.close();
}

编译的完整代码:

   import java.io.*;
   import java.io.File;
   import java.io.FileNotFoundException;
   import java.util.*;
   import java.util.Comparator;
   import java.util.Scanner;
   import java.util.StringTokenizer;

public class GazillionSongs {
   public static void main(String[] args) throws FileNotFoundException, IOException {
      System.out.println("Welcome to Java Song Collection!"); // greets the user
      System.out
      .println("This program sorts and filters large databases of popular songs."); // explains purpose of program
      System.out
      .println("This program is able to filter and sort by year, artist, title and rank.");
      System.out
      .println("Please enter a file that contains a database you wish to filter or sort. (i.e, alistofsongs.txt)"); // sample file = agazillionsongs.txt
      Scanner fileInput = new Scanner(System.in); //Scanner which accepts filename
      String filename = fileInput.nextLine();

      File f = new File(filename); //creates file from input
      /*error check for file here*/
      Scanner fileScanner = new Scanner(f); //inputs data from file

      ArrayList<Song> songs = new ArrayList<Song>();
      while ((fileScanner.hasNextLine())) {
         songs.add(Song.parse(fileScanner.nextLine()));
      }

      System.out
      .println("Please select which commands you would like to use for the program.");
      System.out
      .println("Please format your command like the following example: year:<year(s)> rank:<rank(s)> artist:<artist> title:<title> sortBy:<field>");
      System.out.println();
      System.out.println("You may pick any number of commands you want.");
      System.out
      .println("For years and rank, you may select a range of years or ranks.");
      System.out
      .println("For artists and titles, you may enter a partial name or title.");
      System.out.println("i.e, year:1983 rank:1");
      Scanner input = new Scanner(System.in);

      while (input.hasNextLine()) {
         int n = 0;
         SongCollection collection = new SongCollection(songs);
         String inputType = input.nextLine();
         String delims = "[ ]";
         String[] tokens = inputType.split(delims);
         for (int i = 0; i < tokens.length; i++) {
            n = 0;
            if (n == 0) {
               if ((tokens[i]).contains("year:")) {
                  collection.filterYear(Range.parse(tokens[i]));
                  n = 1;
               }// end of year loop
               if ((tokens[i]).contains("rank:")) {
                  collection.filterRank(Range.parse(tokens[i]));
                  n = 1;
               }// end of rank
               if ((tokens[i]).contains("artist:")) {
                  collection.filterArtist(tokens[i]);
                  n = 1;
               }// end of artist
               if ((tokens[i]).contains("title:")) {
                  collection.filterTitle(tokens[i]);
                  n = 1;
               }// end of title
               if ((tokens[i]).contains("sort:")) {
                     if ((tokens[i]).contains("title")) {
                        collection.sortTitle();
                        n = 1;
                     }// end of sort title
                     if ((tokens[i]).contains("artist")) {
                        collection.sortArtist();
                        n = 1;
                     }// end of sort artist
                     if ((tokens[i]).contains("rank")) {
                        collection.sortRank();
                        n = 1;
                     }// end of sort rank
                     if ((tokens[i]).contains("year")) {
                        collection.sortYear();
                        n = 1;
                     }// end of sort year
               }//end of sort
            }// end of for loop

         }// end of input.hasNextline loop
         final PrintStream console = System.out; //saves original System.out
         File outputFile = new File("output.txt"); //output file
         PrintStream out = new PrintStream(new FileOutputStream(outputFile)); //new FileOutputStream
         System.setOut(out); //changes where data will be printed
         System.out.println(collection.toString());

         System.setOut(console); //changes output to print back to console
         Scanner outputFileScanner = new Scanner(outputFile); //inputs data from file
         while ((outputFileScanner.hasNextLine())) { //while the file still has data
            System.out.println(outputFileScanner.nextLine()); //print
         }
         outputFileScanner.close();
         out.close();
      }
   }// end of main
}// end of class

class Song{
   public enum Order {Year, Rank, Title, Artist}
   public int year;
   public int rank;
   public String artist;
   public String title;

   public static Song parse(String s) {
      Song instance = new Song();
      StringTokenizer tokenizer = new StringTokenizer(s, "\t");
      instance.year = Integer.parseInt(tokenizer.nextToken());
      instance.rank = Integer.parseInt(tokenizer.nextToken());
      instance.artist = (tokenizer.nextToken());
      instance.title = (tokenizer.nextToken());
      return instance;
   }

   public int getYear() {
      return year;
   }

   public int getRank() {
      return rank;
   }

   public String getArtist() {
      return artist;
   }

   public String getTitle() {
      return title;

   }

   public String toString() {
      String output = "\n\nYear = " + year + "\nRank = " + rank + "\nArtist = "
            + artist + "\nTitle = " + title;
      return output;
   }

}
class Range {
   private int min;
   private int max;

   public Range() {
      System.out.println("Please wait.");
   }

   public static Range parse(String s) {
      Range instance = new Range(); // instance is created here so object
                              // variables may be accessed
      String field; // String to contain deleted part of user input
      StringTokenizer tokenizer = new StringTokenizer(s, "-");
      StringTokenizer tokenizer2 = new StringTokenizer(s, ":");// for separating "field:" from the
                                                   // other part of the String
      if (s.contains(":")) { // this deletes the "field:" of the user input so
                        // it does not interfere with the parsing
         field = (tokenizer2.nextToken());
         s = s.replace(field, "");
         s = s.replace(":", "");
      }
      if (s.contains("-")) {
         instance.min = Integer.parseInt(tokenizer.nextToken());
         instance.max = Integer.parseInt(tokenizer.nextToken());

      } else if (!(s.contains("-"))) {
         {
            instance.min = Integer.parseInt(s);
            instance.max = Integer.parseInt(s);
         }
      }
      System.out.println("Range max = " + instance.max);
      System.out.println("Range min = " + instance.min);
      return instance;
   }

   public boolean contains(int n) {
      if (n > min && n < max) { //if the number is contained in the range, method returns true.
         return true;
      } else if (n == min && n == max) {
         return true;
      } else {
         return false;
      }
   }

   public int getMin() {
      return min;
   }

   public int getMax() {
      return max;
   }
}
class SongCollection {
   ArrayList<Song> songs2;
   ArrayList<Song> itemsToRemove = new ArrayList<Song>(); // second collection
                                             // for items to
                                             // remove
   public SongCollection(ArrayList<Song> songs) { // constructor for SongCollection
      System.out.println("Test");
      this.songs2 = songs;
      }
   public void filterYear(Range r) {
      int n = 0;
      if (n == 0) {
         System.out.println("Program is processing.");
         n++;
         for (Song song1 : songs2) {
            if (song1.year > (r.getMax()) || (song1.year) < (r.getMin())) {
               itemsToRemove.add(song1);
            }
         }
         songs2.removeAll(itemsToRemove);
         itemsToRemove.clear();
      }
      System.out.println(songs2);
   }

   public void filterRank(Range r) {
      int n = 0;
      if (n == 0) {
         System.out.println("Program is processing.");
         n++;
         for (Song song1 : songs2) {
            if (song1.rank > (r.getMax()) || (song1.rank) < (r.getMin())) {
               itemsToRemove.add(song1);
            }
         }
         songs2.removeAll(itemsToRemove);
         itemsToRemove.clear();
      }
      System.out.println(songs2);
   }

   public void filterArtist(String s) {
      int n = 0;
      if (n == 0) {
         System.out.println("Program is processing.");
         n++;
         for (Song song1 : songs2) {
            if ((!(((song1.artist).contains(s))))) {
               itemsToRemove.add(song1);
            }
         }
         songs2.removeAll(itemsToRemove);
         itemsToRemove.clear();
      }
      System.out.println(songs2);
   }

   public void filterTitle(String s) {
      int n = 0;
      if (n == 0) {
         System.out.println("Program is processing.");
         n++;
         for (Song song1 : songs2) {
            if ((!(((song1.title).contains(s))))) {
            itemsToRemove.add(song1);
            }
         }
         songs2.removeAll(itemsToRemove);
         itemsToRemove.clear();
      }
      System.out.println(songs2);
   }

   public void sortTitle() {
        Collections.sort(songs2, SongComparator.byTitle()); // now we have a sorted list
        System.out.println(songs2);
      }
   public void sortRank() {
        Collections.sort(songs2, SongComparator.byRank()); // now we have a sorted list
        System.out.println(songs2);
      }
   public void sortArtist() {
        Collections.sort(songs2, SongComparator.byArtist()); // now we have a sorted list
        System.out.println(songs2);
      }
   public void sortYear() {
        Collections.sort(songs2, SongComparator.byYear()); // now we have a sorted list
        System.out.println(songs2);
      }
   public String toString() {
      String result = "";
      for (int i = 0; i < songs2.size(); i++) {
         result += " " + songs2.get(i);
      }

      return result;

   }
}
class SongComparator implements Comparator<Song> {
   public enum Order{
      YEAR_SORT, RANK_SORT, ARTIST_SORT, TITLE_SORT
   }
   private Order sortingBy;
   public SongComparator(Order sortingBy){
      this.sortingBy = sortingBy;
   }
   public static SongComparator byTitle() {
       return new SongComparator(SongComparator.Order.TITLE_SORT);
   }
   public static SongComparator byYear() {
       return new SongComparator(SongComparator.Order.YEAR_SORT);
   }
   public static SongComparator byArtist() {
       return new SongComparator(SongComparator.Order.ARTIST_SORT);
   }
   public static SongComparator byRank() {
       return new SongComparator(SongComparator.Order.RANK_SORT);
   }

   @Override
   public int compare(Song song1, Song song2) {
      switch (sortingBy) {
      case YEAR_SORT:
         return Integer.compare(song1.year, song2.year);
      case RANK_SORT:
         return Integer.compare(song1.rank, song2.rank);
      case ARTIST_SORT:
         return song1.artist.compareTo(song2.artist);
      case TITLE_SORT:
         return song1.title.compareTo(song2.title);
      }
      throw new RuntimeException(
            "Practically unreachable code, can't be thrown");
   }

}

1 个答案:

答案 0 :(得分:0)

您的文本文件数据库中有近37,000首歌曲,以及用户访问它的大量方式(按年份,年份范围,排名,等级范围......),包括排序的可能性,我认为几乎要求您使用一次性流程预处理您的歌曲数据库 - 每次更改数据库时 - 在优先处理数据之前让用户有机会查询反对它。

(我在这里假设您不能使用真正的数据库,这将是理想的解决方案)

我建议的第一件事就是为每首歌曲分配一个唯一的密钥(ID),从1开始,在代码中,应该以长整数表示。将其设为数据库中的第一列。例如,将其命名为agazillionsongs_with_id.txt

1 2008  50 Ashley Tisdale He Said, She Said
2 2008  123   Taylor Swift   Teardrops On My Guitar
3 2008  233   Finger Eleven  Paralyzer
4 2008  258   Paramore Misery Business
...
470  2007  251   Hannah Montana True Friend
471  2006  1  Beyonce  Irreplaceable
...

现在在单独的文本文件中创建其他子表(索引),每个子表只是引用歌曲的键。最简单的是年份索引,可以存储在名为agazillionsongs_sub_year.txt的文件中:

2008 1
2008 2
2008 3
2008 4
...
2007 470
...
2006 471
...

或者,你可以每年以这种形式存储(我更喜欢这种格式)

2008 1, 2, 3, 4, ...
2007 470, ...
2006 471, ...

无论哪种方式,这可以在代码中表示为yearMap对象,它是Map<Integer,List<Song>>,其中值是对相应Song对象的引用。创建这些地图后,将它们输出到文件很容易。

也可以使用等级agazillionsongs_sub_rank.txt / rankMap / Map<Integer,List<Song>>

执行此操作

按名称和标题编制索引比较棘手 - 您是按字母顺序索引整个名称还是使用某些概念&#34;模糊&#34;或仅仅是开头,......?这是一个艰难但重要的概念。

您可以越早了解这个想法,您对数据进行切片和切块的方式越多,用户查询数据库的速度就越快。这是因为每次都需要读完整个歌曲数据库,将每一行放入Song对象中。

相反,此预处理允许您知道完全需要检索数据库中的哪些行。所以你可以忽略所有其他行并丢弃它们。

我希望这会对你有所帮助。