Java字符串索引超出范围:-4

Java字符串索引超出范围:-4,java,parsing,substring,indexof,Java,Parsing,Substring,Indexof,我有一根绳子 statdata = "Health 433 (+78) Attack damage 52.3 (+3.9) Health regen. 6.95 (+0.5) Attack speed 0.64 (+3.7%) Mana 230 (+70) Armor 18 (+3.2) Mana regen. 6.9 (+0.6) Magic res. 30 (+0) Range 150 (Melee) Mov. speed 350"; 我使用substring和indexOf从字符串中提取

我有一根绳子

statdata = "Health 433 (+78) Attack damage 52.3 (+3.9) Health regen. 6.95 (+0.5) Attack speed 0.64 (+3.7%) Mana 230 (+70) Armor 18 (+3.2) Mana regen. 6.9 (+0.6) Magic res. 30 (+0) Range 150 (Melee) Mov. speed 350";
我使用substring和indexOf从字符串中提取数据,并将它们解析为double。这是我的班级:

package Engine;

import WebScraper.getWikiStats;

public class MathParse {
    public static double returnStat;
    public static int indexh;
    public static String statdata;
    public static getWikiStats getStats = new getWikiStats();
    public double stringToDouble(String s){
        s.replaceAll("[^\\d.]", ""); //Remove all characters that aren't a number or a decimal
        double d = Integer.parseInt(s);
        return d;
    }

    public double parseStatData(String stat, String champion){
        statdata = "Health 433 (+78) Attack damage 52.3 (+3.9) Health regen. 6.95 (+0.5) Attack speed 0.64 (+3.7%) Mana 230 (+70) Armor 18 (+3.2) Mana regen. 6.9 (+0.6) Magic res. 30 (+0) Range 150 (Melee) Mov. speed 350";
        System.out.println(statdata);
        if(stat.equalsIgnoreCase("health")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Health") + 7, 3));
        }else if(stat.equalsIgnoreCase("healthpl")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Health") + 10, 3));
        }else if(stat.equalsIgnoreCase("mana")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Mana") + 5, 3));
        }else if(stat.equalsIgnoreCase("manapl")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Mana") + 8, 2));
        }else if(stat.equalsIgnoreCase("healthr")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Health regen.") + 14, 4));
        }else if(stat.equalsIgnoreCase("healthrpl")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Health regen.") + 18, 10));
        }else if(stat.equalsIgnoreCase("manar")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Mana regen.") + 12, 4));
        }else if(stat.equalsIgnoreCase("manarpl")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Mana regen.") + 16, 10));
        }else if(stat.equalsIgnoreCase("range")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Range") + 6, 3));
        }else if(stat.equalsIgnoreCase("ad")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Attack damage") + 14, 5));
        }else if(stat.equalsIgnoreCase("adpl")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Attack damage") + 19, 8));
        }else if(stat.equalsIgnoreCase("as")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Attack speed") + 13, 5));
        }else if(stat.equalsIgnoreCase("aspl")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Attack speed") + 19, 4));
        }else if(stat.equalsIgnoreCase("armor")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Armor") + 6, 4));
        }else if(stat.equalsIgnoreCase("armorpl")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Armor") + 11, 5));
        }else if(stat.equalsIgnoreCase("mr")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Magic res.") + 11, 4));
        }else if(stat.equalsIgnoreCase("mrpl")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Magic res.") + 16, 5));
        }else if(stat.equalsIgnoreCase("ms")){
            returnStat = stringToDouble(statdata.substring(statdata.indexOf("Mov. Speed") + 11, 3));
        }else{
            returnStat = 0;
        }
        return returnStat;
    }
}
以下是使用parseStatData方法时出现的错误:

"main" java.lang.StringIndexOutOfBoundsException: String index out of range: -4
at java.lang.String.substring(Unknown Source)
at Engine.MathParse.parseStatData(MathParse.java:18)
at Champions.champTemplate.showStats(champTemplate.java:27)
at Main.TheoryCrafting.theoryLoop(TheoryCrafting.java:29)
at Main.MainClass.checkCommand(MainClass.java:32)
at Main.MainClass.start(MainClass.java:22)
at Main.MainClass.main(MainClass.java:10)
我不知道出了什么问题,非常感谢您的帮助。

意味着如果第一个参数大于第二个参数,就会抛出一个
索引AutofBoundsException

实际上,子字符串打算采用最低的开始索引,并逐步增加到但不包括您为其提供的最高索引值。它的范围是[a,b]

如果a>b,那么您将选择一个非常奇怪的范围——Java选择在这种情况下出错

罪魁祸首是[可能所有]您的
子字符串
语句:

statdata.substring(statdata.indexOf("Health") + 7, 3);
除非
“Health”
的索引为负值,否则您将始终超出此子字符串的界限

也许您希望颠倒顺序:

statdata.substring(3, statdata.indexOf("Health") + 7);
…虽然,这可能是一个更大问题的解决方案-您试图用子字符串解析一个巨大的字符串,但从长远来看,这是不可维护的

两种解决方案—一种是naive,另一种略优于naive—使用
String[]
Map
保存数据

下面是一个使用地图的解决方案:

Map<String, String> statData = new HashMap<>();

statData.put("Health", "433 (+78)");
statData.put("Attack damage", "52.3 (+3.9)");
// and so forth
Map statData=newhashmap();
"健康,","433(78);;
statData.put(“攻击伤害”,“52.3(+3.9)”);
//诸如此类

鉴于调用
substring
失败,您是否阅读了
String.substring
方法的javadoc?特别是,请查看第二个参数的文档-它并不意味着您认为它意味着什么。Ohhhhh谢谢您,我误读了。我很感激。从中可以学到的一点是始终阅读如果一个方法的行为方式超出了您的预期,则Javadoc将被删除。依赖所有具有特定位数的数字真的是一个好主意吗?也许首先将您的输入划分为标记是有意义的(可能使用
split
方法),然后解析数字,而不依赖它们的特定长度。另外,
double d=Integer.parseInt(s)
对我来说似乎大错特错。你知道
parseInt
做什么,对吗?从问题中的
字符串
可以明显看出,将两个参数反转为
子字符串
根本不是OP想要的。因此,映射的问题是“健康”的值,所有其他值都将发生变化,因为我从一个名为JSoup的api获取statdata字符串,该api允许我从网站获取字符串statdata(我从代码中删除了类以简化它)