2016-02-12 2 views
1

У меня есть два файла, каждый из которых имеет тот же формат, что и около 100 000 строк. Для каждой строки в файле один я извлекаю второй компонент или столбец, и если я найду совпадение во втором столбце второго файла, я извлекаю их третьи компоненты и объединяю их, сохраняю или вывожу.Чтение и сопоставление содержимого двух больших файлов

Хотя моя реализация работает, но программы работают очень медленно, требуется больше часа, чтобы перебирать файлы, сравнивать и выводить все результаты.

Я читаю и сохраняю данные обоих файлов в ArrayList, затем перебираю их по списку и выполняю сравнение. Ниже мой код, есть ли какой-либо сбой производительности, или просто нормальный для такой операции.

Примечание: Я использовал String.split(), но я понимаю, что другое сообщение, что StringTokenizer работает быстрее.

public ArrayList<String> match(String file1, String file2) throws IOException{ 
     ArrayList<String> finalOut = new ArrayList<>(); 
     try { 
      ArrayList<String> data = readGenreDataIntoMemory(file1); 
      ArrayList<String> data1 = readGenreDataIntoMemory(file2); 
      StringTokenizer st = null; 

      for(String line : data){ 
       HashSet<String> genres = new HashSet<>(); 
       boolean sameMovie = false; 
       String movie2 = ""; 
       st = new StringTokenizer(line, "|"); 
       //String line[] = fline.split("\\|"); 
       String ratingInfo = st.nextToken(); 
       String movie1 = st.nextToken(); 
       String genreInfo = st.nextToken(); 
       if(!genreInfo.equals("null")){ 
        for(String s : genreInfo.split(",")){ 
         genres.add(s); 
        } 
       } 


       StringTokenizer st1 = null; 
       for(String line1 : data1){ 
        st1 = new StringTokenizer(line1, "|"); 
        st1.nextToken(); 
        movie2 = st1.nextToken(); 
        String genreInfo2= st1.nextToken(); 
        //If the movie name are similar then they should have the same genre 
        //Update their genres to be the same 
        if(!genreInfo2.equals("null") && movie1.equals(movie2)){ 
         for(String s : genreInfo2.split(",")){ 
          genres.add(s); 
         } 
         sameMovie = true; 
         break; 
        } 
       } 
       if(sameMovie){ 
        finalOut.add(ratingInfo+""+movieName+""+genres.toString()+"\n"); 
       }else if(sameMovie == false){ 
        finalOut.add(line); 
       } 
      } 
     } catch (FileNotFoundException e) { 
      e.printStackTrace(); 
     } 
     return finalOut; 
    } 
+0

для каждой строки в вашем первом файле, которую вы читаете 8 и обрабатываете) с самого начала содержимого второго файла. –

+0

@ScaryWombat, это то, что я делаю. Для каждой строки в первом файле сравнивайте ее со всеми строками во втором файле и, если найдено определенное совпадение, выполните некоторые действия. Это видно из моего кода. Но это очень медленно. – fanbondi

+0

Да, вы делаете это 100000 * 100000 раз. –

ответ

0

Сделайте хеш-соединение.

В настоящее время вы делаете внешний контур присоединиться, который является O (N^2), хэш-соединение будет амортизироваться O (п)

Поместите содержимое каждого файла в хэш-карте, с ключом поле, которое вы хотите (второе поле).

Map<String,String> map1 = new HashMap<>(); 
// build the map from file1 

Затем сделайте хеширования

for(String key1 : map1.keySet()){ 
     if(map2.containsKey(key1)){ 
     // do your thing you found the match 
     } 
    } 
1

Я хотел бы использовать API Streams

String file1 = "files1.txt"; 
String file2 = "files2.txt"; 
// get all the lines by movie name for each file. 
Map<String, List<String[]>> map = Stream.of(Files.lines(Paths.get(file1)), 
              Files.lines(Paths.get(file2))) 
     .flatMap(p -> p) 
     .parallel() 
     .map(s -> s.split("[|]", 3)) 
     .collect(Collectors.groupingByConcurrent(sa -> sa[1], Collectors.toList())); 

// merge all the genres for each movie. 
map.forEach((movie, lines) -> { 
    Set<String> genres = lines.stream() 
      .flatMap(l -> Stream.of(l[2].split(","))) 
      .collect(Collectors.toSet()); 
    System.out.println("movie: " + movie + " genres: " + genres); 
}); 

Это имеет то преимущество, что O(n) вместо O(n^2) и это многопоточный.

Смежные вопросы