查找字符串的所有子字符串 - StringIndexOutOfBoundsException

时间:2013-07-03 16:34:06

标签: java algorithm indexoutofboundsexception substring

我创建了Word类。 Word有一个构造函数,它接受一个字符串参数和一个方法getSubstrings,它返回一个包含word的所有子字符串的String,按长度排序。

例如,如果用户提供输入“rum”,则该方法返回a 将打印的字符串如下:

r
u
m
ru
um
rum 

我想连接String中的子串,用换行符分隔它们(“\ n”)。然后返回字符串。

代码:

    public class Word {
    String word;

    public Word(String word) {
        this.word = word;
    }
    /**
     * Gets all the substrings of this Word.
     * @return all substrings of this Word separated by newline
     */

    public String getSubstrings()
    {
        String str = "";
        int i, j;
        for (i = 0; i < word.length(); i++) {
            for (j = 0; j < word.length(); j++) {
                str = word.substring(i, i + j);
                str += "\n";
            }
        }
        return str;
    }

但它抛出异常:

java.lang.StringIndexOutOfBoundsException: String index out of range: -1
    at java.lang.String.substring(String.java:1911)

我坚持这一点。也许,根据此方法签名public String getSubstrings(),您有其他建议 如何解决这个问题?

3 个答案:

答案 0 :(得分:6)

异常分析:

来自Java7 Docs of StringIndexOutOfBoundsException

public class StringIndexOutOfBoundsException extends IndexOutOfBoundsException
  

按字符串方法抛出,表示索引为负数或大于字符串的大小。

来自Java 7 Docs of substring

public String substring(int beginIndex,int endIndex)
  

返回一个新字符串,该字符串是此字符串的子字符串。子字符串从指定的beginIndex开始,并扩展到索引endIndex - 1处的字符。因此子字符串的长度为endIndex-beginIndex。

我猜这个:子串的长度是endIndex-beginIndex 进入String index out of range: -1。我已经对多个案例进行了测试,认为我的假设是正确的,但感谢任何其他证据。

对于-1:"rum".substring(2,1);会给你String index out of range: -1

Parameters:
    beginIndex - the beginning index, inclusive.
    endIndex - the ending index, exclusive.

StringIndexOutOfBoundsException的原因

在给定的代码段中,substring正在尝试获取字符串,其长度超过字符串的总长度endIndexi+j将超过字符串的总长度):

str = word.substring(i, i + j);

考虑i = 2且j = 2的情况,单词“rum”

然后str=word.substring(2, 4); 不可能

类似于问题中提供的代码段的解决方案:

这应该可以解决问题:

 public String getSubstrings()
    {
        String str="",substr = "";
        for (int i = 0; i < word.length(); i++) {
            for (int j = 0; i+j <= word.length(); j++) { //added i+j and equal to comparison
               substr = word.substring(j, i + j); //changed word.substring(i, i + j) to word.substring(j, i + j)
               if("".equals(substr))continue; //removing empty substrings
               str += substr; //added concatenation + operation
               str += "\n";
            }
        }
        return str+word;
    }

测试用例:

对于word="rum",这将给出输出:

r
u
m
ru
um
rum

答案 1 :(得分:4)

你的逻辑似乎令人费解,是异常的来源:

str = word.substring(i, i + j);

考虑您的ij两者等于word.length()-1,然后substring()将失败。

您可以这样做:

public String getSubstrings(String word){
   StringBuilder sub= new StringBuilder();
   for( int i = 0 ; i < word.length() ; i++ )
   {
      for( int j = 1 ; j <= word.length() - i ; j++ )
      {
         sub .append(word.substring(i, i+j)).append("\n");
      }
   }
   return sub.toString();
}

注意:如果您要在String上进行大量连接,请考虑使用StringBuilder代替String

答案 2 :(得分:1)

我意识到我在这个派对上有点迟了,而且我自己是一个非常新的程序员 - 但是我在尝试编写类似的方法时遇到了同样的错误。

对我来说,它有助于将嵌套for循环的计数器变量重命名为描述它们所跟踪内容的名称。对于外循环,我使用int subLength,对于内循环,我使用int position(起始位置)。我确定还有其他方法可以做到这一点,但我很满意我的解决方案。这是一些伪代码,我希望能帮助那些看起来这个问题的人:

     for each possible substring length 1 up to and including the original word length: 
            generate substrings starting at the 0th position, and then starting at each 
            proceeding letter up to but not including (word.length() - (subLength - 1))