2016-07-12 2 views
0

Я построил довольно простую программу, которая берет информацию из файла .txt и помещает ее в список, сортирует ее, а затем удаляет дубликаты, помещая ее в TreeSet.Удалите необходимость перебора списка для каждого элемента.

Если посмотреть на countInstance() и как это называется, вы увидите, что для каждой итерации TreeSet метод запуска, а затем он перебирает список по dataToSplit несколько раз. Я считаю, что он повторяет список 30 раз в этом конкретном случае.

Вопрос
Есть ли способ удалить необходимость повторного итерации списка столько раз и при этом достичь тех же результатов?

import java.io.BufferedReader; 
import java.io.File; 
import java.io.FileReader; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Set; 
import java.util.TreeSet; 

public class TallyCounter { 
    private void tallyCount(File commaSeperated) { 
     List<String> dataToSplit = new ArrayList<String>(); 
     Set<String> set; 

     try { 
      BufferedReader br = new BufferedReader(new FileReader(commaSeperated)); 
      String currentLine; 
      while ((currentLine = br.readLine()) != null) { 
       String[] tempArray = currentLine.split(","); 
       for(String s : tempArray) { 
        dataToSplit.add(s.replaceAll("\t", "").replaceAll("\n", "").trim()); 
       } 
      } 

      br.close(); 
     } catch(Exception e) { 
      e.printStackTrace(); 
     } 

     dataToSplit.sort(new AlphanumComparator()); 
     set = new TreeSet<String>(dataToSplit); 


     System.out.println("String Tally Count"); 
     for(String s : set) { 
      System.out.println(countInstance(s, dataToSplit)); 
     } 
    } 

    private String countInstance(String s, List<String> l) { 
     int count = 0; 

     for(String temp : l) { 
      if(s.equals(temp)) { 
       count++; 
      } 
     } 

     int rSpace = (10 - count)/2; 

     String repeated = new String(new char[count]).replace("\0", "|"); 
     String space = new String(new char[rSpace]).replace("\0", " "); 

     return " " + s + " " + space + repeated + " " + space + Integer.toString(count); 
    } 


    public static void main(String[] args) { 
     TallyCounter tC = new TallyCounter(); 
     tC.tallyCount(new File("src/txt.txt")); 
    } 
} 

Дополнительные детали

AlphanumComparator.java

import java.util.Comparator; 

public class AlphanumComparator implements Comparator<Object> 
{ 
    private final boolean isDigit(char ch) 
    { 
     return ch >= 48 && ch <= 57; 
    } 

    /** Length of string is passed in for improved efficiency (only need to calculate it once) **/ 
    private final String getChunk(String s, int slength, int marker) 
    { 
     StringBuilder chunk = new StringBuilder(); 
     char c = s.charAt(marker); 
     chunk.append(c); 
     marker++; 
     if (isDigit(c)) 
     { 
      while (marker < slength) 
      { 
       c = s.charAt(marker); 
       if (!isDigit(c)) 
        break; 
       chunk.append(c); 
       marker++; 
      } 
     } else 
     { 
      while (marker < slength) 
      { 
       c = s.charAt(marker); 
       if (isDigit(c)) 
        break; 
       chunk.append(c); 
       marker++; 
      } 
     } 
     return chunk.toString(); 
    } 

    public int compare(Object o1, Object o2) 
    { 
     if (!(o1 instanceof String) || !(o2 instanceof String)) 
     { 
      return 0; 
     } 
     String s1 = (String)o1; 
     String s2 = (String)o2; 

     int thisMarker = 0; 
     int thatMarker = 0; 
     int s1Length = s1.length(); 
     int s2Length = s2.length(); 

     while (thisMarker < s1Length && thatMarker < s2Length) 
     { 
      String thisChunk = getChunk(s1, s1Length, thisMarker); 
      thisMarker += thisChunk.length(); 

      String thatChunk = getChunk(s2, s2Length, thatMarker); 
      thatMarker += thatChunk.length(); 

      // If both chunks contain numeric characters, sort them numerically 
      int result = 0; 
      if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0))) 
      { 
       // Simple chunk comparison by length. 
       int thisChunkLength = thisChunk.length(); 
       result = thisChunkLength - thatChunk.length(); 
       // If equal, the first different number counts 
       if (result == 0) 
       { 
        for (int i = 0; i < thisChunkLength; i++) 
        { 
         result = thisChunk.charAt(i) - thatChunk.charAt(i); 
         if (result != 0) 
         { 
          return result; 
         } 
        } 
       } 
      } else 
      { 
       result = thisChunk.compareTo(thatChunk); 
      } 

      if (result != 0) 
       return result; 
     } 

     return s1Length - s2Length; 
    } 
} 

txt.txt

5.00, 5.14, 5.01, 4.90, 5.02, 5.18, 5.04, 5.07, 4.95, 5.05 
5.05, 4.82, 4.97, 5.04, 4.98, 5.12, 5.08, 4.96, 5.02, 4.93 
5.12, 5.04, 5.13, 4.94, 5.06, 5.00, 4.92, 5.17, 5.08, 4.99 
5.07, 5.15, 5.01, 4.95, 5.11, 5.22, 5.08, 4.86, 4.97, 5.14 
5.03, 5.14, 5.06, 4.88, 4.96, 5.04, 4.96, 5.09, 4.93, 5.03 

сноска

Я извиняюсь за то, как странно выглядит результат, когда он запускается. Это связано только с тем, что я еще не реализовал JTable для хранения информации.

+0

Я считаю себя потерял, как к тому, что вы пытаетесь сделать, и какой формат вашего вклада. – Zircon

+0

Не совсем ответ на ваш вопрос, поскольку он уже был дан ответ, но нет необходимости подсчитывать частоту элемента в списке. Рамка коллекций уже предоставляет метод для этого: Collections.frequency. Не то чтобы вы могли использовать его в этом случае. – Renatols

+0

@Renatols Спасибо за информацию, но я знал об этом методе. Проблема с его использованием заключается в том, что он выполняет итерацию списка, как моя, поэтому она может быть немного более эффективной, чем моя версия, но не сильно – Dan

ответ

2

Используйте HashMap<String,Integer> countMap и проследуйте через строки один раз. С каждым temp вы найдете, добавьте 1 к соответствующему значению countMap.get(temp) в HashMap.

0

Я предлагаю вам использовать hash set вместо набора деревьев. Хэш позволяет вам напрямую получать нужные данные, а не итерировать через всех участников. Он имеет постоянное время вставки и запроса. Кроме того, если вы хотите связать каждую строку с количеством экземпляров, которые она появляется, вы можете использовать хеш-карту вместо набора и сопоставить строки с Integer.

Это не самый простой способ следить за тем, что вы делаете. Вы были очень кратки в своем описании и не комментировали свой код; Я предлагаю вам исправить обе эти проблемы. Потребовалось несколько минут, чтобы проанализировать ваш код и понять, что вы пытаетесь сделать и как вы пытались это сделать. Вы получите дополнительную помощь, если мы сразу поймем вопрос.

0

Я хотел бы использовать вместо HashMap<String, Integer>HashMap<Double, Integer>

private void tallyCount(File commaSeperated) { 
    HashMap<Double, Integer> map = new HashMap<>(); 

    try { 
     BufferedReader br = new BufferedReader(new FileReader(commaSeperated)); 
     String currentLine; 
     while ((currentLine = br.readLine()) != null) { 
      String[] tempArray = currentLine.split(","); 
      for(String s : tempArray) { 
       double value = Double.parseDouble(s); 
       if (map.containsKey(value)) { 
        map.replace(value, map.get(value) + 1); 
       } else { 
        map.put(value, 1); 
       } 
      } 
     } 

     br.close(); 
    } catch(Exception e) { 
     e.printStackTrace(); 
    } 

    map.entrySet().stream() 
        .sorted(Map.Entry.comparingByKey()) 
        .forEach(e -> System.out.println(e.getKey() + "|" + e.getValue())); 
} 


public static void main(String[] args) { 
    TallyCounter tC = new TallyCounter(); 
    tC.tallyCount(new File("src/txt.txt")); 
} 
Смежные вопросы