0

This is for a homework assignment. I am trying to make a program that searches a text file for specific words and then prints out the frequency of the word.

public class WordFreq extends Echo{

ArrayList<WordCount>array1=new ArrayList<WordCount>();
String[] words;
int wordsTotal=0;


public WordFreq(String f, String x) throws IOException
{
  super(f);
  words=x.toLowerCase().split(" ");
}

public void processLine(String line){ 
  String[] lines=line.toLowerCase().split(" ");
  wordsTotal=wordsTotal+lines.length;
  for(int j=0; j<lines.length; j++){
    WordCount alpha=new WordCount(lines[j]);
    alpha.incCount();
    array1.add(alpha);}
  for(int x=0; x<array1.size(); x++){
    for(int y=0; y<array1.size(); y++){
      if(array1.get(x).equals(array1.get(y))&&(x!=y)){
        for(int i = 0; i< array1.get(y).getCount(); i++){
          array1.get(x).incCount();
        }
        array1.remove(y);
      }
    }
  }

}

public void reportFrequencies(){
  for(int i = 0; i<array1.size();i++){
    // System.out.println(array1.get(i).getWord()+" "+array1.get(i).getCount());
  }
  int currentWord=0;
  for(int x=0; x<words.length; x++){
    for(int y=0; y<array1.size(); y++){
      if(words[x].equals(array1.get(y).getWord())){
        currentWord=array1.get(y).getCount();}}
    System.out.print(words[x]+" ");
    System.out.printf("%.4f",(double)currentWord/wordsTotal);
  }
}

}

Here is my main method:

public class FreqStudy{
  public static void main(String[] args) throws IOException
  {
    Scanner scan = new Scanner(System.in);
    System.out.println("enter file name");
    String fileName = scan.next();
    Scanner scan2 = new Scanner(System.in);
    System.out.println("enter words to search for");
    System.out.println("enter lower case, separated by spaces");
    String wordString = scan2.nextLine();
    WordFreq f = new WordFreq(fileName,wordString);
    f.readLines();
    f.reportFrequencies();
  }
}

I am using a .txt file of the book Emma by Jane Austen. This is the error message that I get when I run the program and try to search for words:

java.lang.IndexOutOfBoundsException: Index: 906, Size: 906
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.get(ArrayList.java:322)
at WordFreq.processLine(WordFreq.java:26)
at Echo.readLines(Echo.java:16)
at FreqStudy.main(FreqStudy.java:15)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at edu.rice.cs.drjava.model.compiler.JavacCompiler.runCommand(JavacCompiler.java:272)"

Here are the codes for Echo and WordCount:

public class WordCount{

private String word;
private int count;

public WordCount(String w){
word = w;
count = 0;
}

public String getWord(){
return word;}

public int getCount(){
return count;}

public void incCount(){count++;}

public String toString() {
return(word +  " --- " + count);
}

public boolean equals(Object other){
WordCount i = (WordCount)other;
return (this.word.equals(i.word));
}
}

echo:

import java.util.Scanner;
import java.io.*;


public class Echo{
String fileName; // external file name
Scanner scan; // Scanner object for reading from external file

public Echo(String f) throws IOException
{
fileName = f;
scan = new Scanner(new FileReader(fileName));
}

public void readLines(){ // reads lines, hands each to processLine
while(scan.hasNext()){
  processLine(scan.nextLine());
}
scan.close();
}

public void processLine(String line){ // does the real processing work
System.out.println(line);
}
}

Line 26 of my code is:

for(int i = 0; i< array1.get(y).getCount(); i++)
user2163240
  • 17
  • 2
  • 4

3 Answers3

0

In your nested for loops, you're looping against the size of array1 at the same time as you're manipulating array1. Don't alter anything you're using to iterate while iterating. You might consider copying array1 to iterate over.

for(int x=0; x<array1.size(); x++){
    for(int y=0; y<array1.size(); y++){
        if(array1.get(x).equals(array1.get(y))&&(x!=y)){
            for(int i = 0; i< array1.get(y).getCount(); i++){
                 array1.get(x).incCount();
            }
            array1.remove(y); // NO NO NO
        }
    }
}
thegrinner
  • 11,546
  • 5
  • 41
  • 64
0

I think your issue is that your using array1.size() for your boundary yet inside the for-loop you are removing values from array1. So your y counter is incrementing and your boundary is always decreasing. At a specific point in the loop this increment/decrements is going to causing a situation where Y will become greater than array1.size so when you try to do a get(y) you will be out of bounds.

try something like

int size = array1.size();  //outside the for loops
....
for(int y=0; y<size; y++){
Raymond Holguin
  • 1,050
  • 2
  • 12
  • 35
0

If you want to change the object you are iterating over I would suggest using an Iterator.

You can get the iterator over your ArrayList by doing this:

Iterator<WordCount> iterator = array1.iterator();

This could potentially solve your problem and simplify your code. Just be sure to use:

iterator.remove() instead of array1.remove(index) etc.

webermaster
  • 209
  • 1
  • 13