简体   繁体   English

迭代列表时出现奇怪的outOfBoundsException

[英]Strange outOfBoundsException when iterating through lists

I'm writing a program that applies many principles of computational linguistics. 我正在编写一个应用了许多计算语言学原理的程序。 My problem at this moment is the following piece of code form a method that "flexibilizes two definitions". 我现在的问题是下面的一段代码构成了一个“灵活化两个定义”的方法。 This is, it compares two different definitions of the same word, and in each definition empty or blank spaces will be added to later on work with the altered definitions (with blank spaces added). 也就是说,它比较了同一个单词的两个不同定义,并且在每个定义中,将添加空或空格以便稍后使用更改的定义(添加空格)。
Say we have the following two definitions, defining the term "free fall". 假设我们有以下两个定义,定义术语“自由落体”。

1) Free fall descent  of a body subjected only to            the   action of  gravity.
2) Free fall movement of a body in        a    gravitational field under  the influence of gravity

There is a list of words called stoplist, which contains the words: "of", "a", "in", "to", and "under". 有一个名为stoplist的单词列表,其中包含单词:“of”,“a”,“in”,“to”和“under”。 After the process, each word in the definition that is also contained in the stoplist must correspond to a blank space OR another stoplist word of the other definition. 在该过程之后,定义中也包含在停止列表中的每个单词必须对应于空白空间或另一个定义的另一个停止列表单词。 So after executing such process, the previous definitions, represented in two different lists, should look like this: 因此,在执行此类过程之后,以两个不同列表表示的先前定义应如下所示:

1) Free fall descent  of a body ____ ____ subjected     only  to     the action    of gravity.
2) Free fall movement of a body in   a    gravitational field under  the influence of gravity.

The code I wrote to achieve this is the following: 我为实现这个目的而编写的代码如下:


[...]

String[] sList = STOPLIST.split(" ");  //this is the stoplist
String[] definition1 = defA1.split(" ");  //this is the array of words of the first definition
String[] definition2 = defA2.split(" ");  //this is the array of words of the second definition
List<String> def1 = new ArrayList<String>();  
List<String> def2 = new ArrayList<String>();
List<String> stopList = new ArrayList<String>();

for(String word : definition1){
    def1.add(word); //I transform arrays into lists this way because I used to think that using .asList() was the problem.
}
for(String word : definition2){
    def2.add(word);
}
for(String word : sList){
    stopList.add(word);
}

int mdef = (def1.size() <= def2.size()) ? def1.size() : def2.size(); //here mdef will have the value of the lenght of the shortest definition, and we are going to use the value of mdef to iterate later on.

for(int i = 0; i < mdef; i++){
    if (stopList.contains(def1.get(i))) {  //here I check if the first word of the first definition is also found in the stoplist.
        if (!stopList.contains(def2.get(i))) {  //If the word of def1 previously checked is in the stoplist, as well as the corresponding word in the second definition, then we won't add a " "(blank) space in the corresponding position of the second definition.
           def2.add(i , " "); //here I add that blank space, only if the stoplist word in def1 corresponds to a non-stoplist word in def2. Again, we do this so the stoplist word in def1 corresponds to a blank space OR another stoplist word in def2.
           if(mdef == def2.size())
               mdef++; //In case the shortest definition is the definition to which we just added spaces, we increment mdef++, because that space added increases the length of the shortest definition, and to iterate in this recenlty extended definiton, we have to increment the index with which we iterate.
        }
    } else if (stopList.contains(def2.get(i))) { //this else if does the same than the previous one, but checks for the second definition instead of the first one. And adds blanks to def1 instead of def2 if necessary.
        if (!stopList.contains(def1.get(i))) {
            def1.add(i , " ");
            if(mdef == def1.size())
                mdef++;
        }
    }
}

[...]

Now, if you analyze the code carefully, you will realize that not all words of the lengthiest list will be checked, given that we iterate ove the definitions using the lenght of the shortest definition as index. 现在,如果仔细分析代码,您将意识到不会检查最长列表中的所有单词,因为我们使用最短定义的长度作为索引来迭代定义。 This is fine, the remainding words of the lenghtiest definitions don't have to be checked, they will correspond to null spaces of the other definition (in case the lists don't end up being of the same lenght after the addition of spaces, as the previous exaple shows). 这很好,不必检查最长定义的剩余单词,它们将对应于另一个定义的空格(如果列表在添加空格后最终没有相同的长度,正如之前的exaple所示)。

Now, after the explanation, the problem is the following: after running the main class, which calls the method that contains the previous code, a runtime exceptions pops out: 现在,在解释之后,问题如下:在运行主类(调用包含前面代码的方法)之后,弹出运行时异常:

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 1, Size: 0
    at java.util.ArrayList.rangeCheck(ArrayList.java:571)
    at java.util.ArrayList.get(ArrayList.java:349)
    at main2.main(main2.java:75)

I don't understand why it is finding any of the lists as "empty". 我不明白为什么它发现任何列表为“空”。 I have tried to solve it in too many ways, I hope a I gave a good explanation. 我试图以太多方式解决它,我希望我给出了一个很好的解释。

It may help as a clue that if I assign mdef to the lengthiest size instead of the shortest, that is : 它可能有助于作为一个线索,如果我将mdef分配给最长的大小而不是最短的,那就是:

int mdef = (def1.size() >= def2.size()) ? def1.size() : def2.size();

the error changes to: 错误更改为:

Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 15, Size: 15
    at java.util.ArrayList.rangeCheck(ArrayList.java:571)
    at java.util.ArrayList.get(ArrayList.java:349)
    at asmethods.lcc.turnIntoFlex(lcc.java:55)
    at asmethods.lcc.calLcc(lcc.java:99)
    at main2.main(main2.java:73)' 

Where lcc is the class that contains the method turnIntoFlex that contains the piece of code I'm showing. 其中lcc是包含方法turnIntoFlex的类,其中包含我正在显示的代码段。 The line 55 of "turnIntoFlex" corresponds to the first line of the loop, that is: “turnIntoFlex”的第55行对应于循环的第一行,即:

if (stopList.contains(def1.get(i))) { [...]

Comments: The values of defA1 and defA2 are the definitions, respectively. 注释:defA1和defA2的值分别是定义。 ie def1 and def2, initially, are lists in which each separate element is a word. 即def1和def2,最初是列表,其中每个单独的元素是一个单词。 I can't check if these lists are being populated by printing them because the indexoutofboundsexception pops at the very moment the loop starts. 我无法通过打印来检查是否正在填充这些列表,因为indexoutofboundsexception在循环开始时弹出。 However, I do print the values of the sizes of mdef, def1.size() and def2.size(), and the values turn out to be 13, or 15, showing that no list is empty before the "for" loop starts. 但是,我打印mdef,def1.size()和def2.size()的大小的值,并且值变为13或15,表明在“for”循环开始之前没有列表为空。

The mdef++ was something I added recently, not to exactly to solve this specific problem, but the error has been popping since before I added the mdef++ part. mdef ++是我最近添加的,不是为了解决这个特定的问题,但是在添加mdef ++部分之前错误已经弹出。 As I explained, The intention is to increase mdef++ when the shortest list is extended (but only when the short list is extended) so we iterate through all the words of the short list, and not more. 正如我所解释的那样,目的是在扩展最短列表时增加mdef ++(但仅在扩展短列表时),因此我们遍历短列表中的所有单词,而不是更多。

the problem your running in to is with the increment. 你输入的问题是增量。 try this: 尝试这个:

for(int i = 0; i < mdef; i++){
    if (stopList.contains(def1.get(i))) {  //here I check if the first word of the first definition is also found in the stoplist.
        if (!stopList.contains(def2.get(i))) {  //If the word of def1 previously checked is in the stoplist, as well as the corresponding word in the second definition, then we won't add a " "(blank) space in the corresponding position of the second definition.
            def2.add(i , " "); //here I add that blank space, only if the stoplist word in def1 corresponds to a non-stoplist word in def2. Again, we do this so the stoplist word in def1 corresponds to a blank space OR another stoplist word in def2.
            mdef=Math.min(def2.size(),def1.size);

        }
    } else if (stopList.contains(def2.get(i))) { //this else if does the same than the previous one, but checks for the second definition instead of the first one. And adds blanks to def1 instead of def2 if necessary.
        if (!stopList.contains(def1.get(i))) {
            def1.add(i , " ");
            mdef=Math.min(def2.size(),def1.size);
        }
    }
}

Let's look at this: 我们来看看这个:

for(int i = 0; i < mdef; i++){
    if (stopList.contains(def1.get(i))) {  //here I check if the first word of the first definition is also found in the stoplist.
        if (!stopList.contains(def2.get(i))) {  //If the word of def1 previously checked is in the stoplist, as well as the corresponding word in the second definition, then we won't add a " "(blank) space in the corresponding position of the second definition.
            def2.add(i , " "); //here I add that blank space, only if the stoplist word in def1 corresponds to a non-stoplist word in def2. Again, we do this so the stoplist word in def1 corresponds to a blank space OR another stoplist word in def2.
            if(mdef == def2.size())
                mdef++; //In case the shortest definition is the definition to which we just added spaces, we increment mdef++, because that space added increases the length of the shortest definition, and to iterate in this recenlty extended definiton, we have to increment the index with which we iterate.
        }
    }
}

forgetting about the else if for a second. 忘了else if一秒钟。

Suppose you started with both def1 and def2 of size 1. so mdef=1 . 假设你从大小为1的def1def2开始。所以mdef=1

you went into the if() , added an entry to def2 , and incremented mdef . 你进入了if() ,在def2添加了一个条目,并增加了mdef Now 现在

  • def1.size()=1
  • def2.size()=2
  • mdef=2
  • i=0

next iteration: i++ => i=1; i < mdef? true 下一次迭代: i++ => i=1; i < mdef? true i++ => i=1; i < mdef? true i++ => i=1; i < mdef? true => enter the loop i++ => i=1; i < mdef? true =>进入循环

def1.get(1) throws an exception, since you're going for element at index 1 in a list size 1. def1.get(1)抛出异常,因为你要在列表大小为1的索引1处使用元素。

This should work: 这应该工作:

if (i < def1.size() && stopList.contains(def1.get(i))) {
  ...
}

and likewise in else if 而且else if

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM