Группировка слов из текстового файла в Arraylist на основе длины

#java #arraylist #hashmap

#java #arraylist #hashmap

Вопрос:

 public class JavaApplication13 {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
         BufferedReader br;
        String strLine;
        ArrayList<String> arr =new ArrayList<>();
        HashMap<Integer,ArrayList<String>> hm = new HashMap<>();
        try {
            br = new BufferedReader( new FileReader("words.txt"));
            while( (strLine = br.readLine()) != null){
                arr.add(strLine);
            }
        } catch (FileNotFoundException e) {
            System.err.println("Unable to find the file: fileName");
        } catch (IOException e) {
            System.err.println("Unable to read the file: fileName");
        }


        ArrayList<Integer> lengths = new ArrayList<>(); //List to keep lengths information 


        System.out.println("Total Words: " arr.size()); //Total waords read from file

        int i=0;
        while(i<arr.size()) //this loop will itrate our all the words of text file that are now stored in words.txt
        {
            boolean already=false;
            String s = arr.get(i);
            //following for loop will check if that length is already in lengths list.
            for(int x=0;x<lengths.size();x  )
            {
                if(s.length()==lengths.get(x))
                    already=true;
            }
           //already = true means file is that we have an arrayist of the current string length in our map
            if(already==true)
            {

                hm.get(s.length()).add(s); //adding that string according to its length in hm(hashmap)
            }
            else
            {
                    hm.put(s.length(),new ArrayList<>()); //create a new element in hm and the adding the new length string
                    hm.get(s.length()).add(s);
                    lengths.add(s.length());

            }

            i  ;
        }
        //Now Print the whole map
        for(int q=0;q<hm.size();q  )
        {
            System.out.println(hm.get(q));
        }
    }

}
  

является ли этот подход правильным?

Объяснение:

  1. загрузите все слова в ArrayList.
  2. затем выполните итерацию по каждому индексу и проверьте длину слова, добавьте его в ArrayList строк, содержащих эту длину, где эти ArrayList отображаются в hashmap с длиной слов, которые он содержит.

Ответ №1:

Во-первых, ваш код работает только для файлов, содержащих по одному слову в строке, поскольку вы обрабатываете целые строки как слова. Чтобы сделать ваш код более универсальным, вы должны обрабатывать каждую строку, разбивая ее на слова:

 String[] words = strLine.split("\s ")
  

Во-вторых, вам не нужны никакие временные структуры данных. Вы можете добавить свои слова на карту сразу после того, как прочитаете строку из файла. arr и lengths списки здесь фактически бесполезны, поскольку они не содержат никакой логики, кроме временного хранения. Вы используете lengths list только для хранения длин, которые уже были добавлены на hm карту. То же самое может быть достигнуто путем вызова hm.containsKey(s.length()) .

И дополнительный комментарий к вашему коду:

     for(int x=0;x<lengths.size();x  ) {
        if(s.length()==lengths.get(x))
            already=true;
    }
  

когда у вас есть подобный цикл, когда вам нужно только найти, выполняется ли какое-либо условие для любого элемента, вам не нужно продолжать цикл, когда условие уже найдено. Вы должны использовать break ключевое слово внутри вашего оператора if для завершения блока цикла, например

     for(int x=0;x<lengths.size();x  ) {
        if(s.length()==lengths.get(x))
            already=true;
            break; // this will terminate the loop after setting the flag to true
    }
  

Но, как я уже упоминал, вам это вообще не нужно. Это просто для образовательных целей.

Комментарии:

1. Очень полезно, я собираюсь внести изменения

Ответ №2:

Ваш подход длинный, запутанный, сложный для отладки, и, насколько я вижу, он не очень хорош с точки зрения производительности (ознакомьтесь с contains методом). Проверьте это:

 String[] words = {"a", "ab", "ad", "abc", "af", "b", "dsadsa", "c", "ghh", "po"};
Map<Integer, List<String>> groupByLength =
  Arrays.stream(words).collect(Collectors.groupingBy(String::length));
System.out.println(groupByLength);
  

Это всего лишь пример, но вы поняли суть. У меня есть массив слов, а затем я использую потоки и Java8 магию, чтобы сгруппировать их на карте по длине (именно то, что вы пытаетесь сделать). Вы получаете поток, затем собираете его на карту, группируя по длине слов, так что каждое слово из 1 буквы будет помещено в список под ключом 1 и т. Д.

Вы можете использовать тот же подход, но у вас есть свои слова в списке, поэтому не забывайте использовать Arrays.stream() , а просто .stream() в своем списке.