根据字符串列表索引计算双精度列表总成本时遇数组越界异常
问题分析与修复方案
首先,你的代码抛出java.lang.IndexOutOfBoundsException主要有几个核心原因,同时循环逻辑也存在不少漏洞,咱们逐个梳理清楚:
1. 直接访问空列表totCost的元素
totCost初始化后是空的,但你在循环里直接调用totCost.get(i)——这时候列表里还没有任何元素,自然会触发索引越界异常。你需要先给totCost初始化对应数量的0.0值,和singDeploy的长度保持一致。
2. 内层循环的条件写错了
内层循环的条件写成了i<deploy.size(),这完全是笔误!应该是j<deploy.size()。这个错误会导致j一直自增,直到超过deploy的长度,触发deploy.get(j)的索引越界。
3. 字符串比较用了==而非equals()
Java里字符串比较内容要用equals(),==比较的是对象的内存地址,即使两个字符串内容完全一样,也可能返回false,导致你的匹配逻辑完全失效。
4. 多余的j++导致跳步
内层循环的else块里写了j++,但for循环本身已经有j++的操作,这会让j每次跳过一个元素,导致部分rate值被遗漏。
5. 错误使用totCost.add()修改值
totCost.add()是往列表末尾添加新元素,而不是修改已有索引的元素。你需要用totCost.set(i, 新值)来更新对应位置的总和。
修复后的完整代码
import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class DeployCostCalculator { public static void main(String[] args) { List<String> deploy = new ArrayList<>(); List<String> singDeploy = new ArrayList<>(); List<Double> totCost = new ArrayList<>(); List<Double> rate = new ArrayList<>(); // 初始化数据 singDeploy.addAll(Arrays.asList("Green Cow", "Green Elephant", "Green Rhinocerous", "Purple Cow", "Yellow Cat", "Red Sloth")); deploy.addAll(Arrays.asList("Green Cow", "Green Cow", "Green Elephant", "Green Cow", "Green Cow", "Green Rhinocerous", "Purple Cow", "Yellow Cat", "Red Sloth", "Green Cow", "Purple Cow", "Green Cow", "Red Sloth", "Yellow Cat", "Green Rhinocerous", "Purple Cow")); rate.addAll(Arrays.asList(0.553683754016, 1.02150872447, 0.134625067987, 1.98664453833, 0.861269450714, 0.36946659851, 0.909230205525, 0.00248039618935, 0.160619970732, 0.545320579333, 0.0709241158945, 3.96782782573E-6, 0.849530002338, 1.29965105158, 6.72974424027E-6, 4.51463564725E-6)); // 初始化totCost为0.0,和singDeploy长度一致 for (int i = 0; i < singDeploy.size(); i++) { totCost.add(0.0); } // 遍历每个去重后的部署项 for (int i = 0; i < singDeploy.size(); i++) { String currentSing = singDeploy.get(i); // 遍历原始部署列表,累加对应rate for (int j = 0; j < deploy.size(); j++) { if (currentSing.equals(deploy.get(j))) { // 获取当前总和,加上新的rate值,再更新回去 double currentTotal = totCost.get(i); currentTotal += rate.get(j); totCost.set(i, currentTotal); } // 去掉多余的j++,for循环会自动处理 } } // 验证结果 for (int i = 0; i < singDeploy.size(); i++) { System.out.println(singDeploy.get(i) + " 的总费用: " + totCost.get(i)); } } }
额外优化建议
如果数据量很大,嵌套循环的时间复杂度是O(n*m),可以用HashMap来优化,先把deploy和rate的对应关系按字符串分组求和,再映射到singDeploy的顺序,这样时间复杂度能降到O(n+m):
import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; public class DeployCostCalculatorOpt { public static void main(String[] args) { List<String> deploy = new ArrayList<>(); List<String> singDeploy = new ArrayList<>(); List<Double> totCost = new ArrayList<>(); List<Double> rate = new ArrayList<>(); // 初始化数据(同上) singDeploy.addAll(Arrays.asList("Green Cow", "Green Elephant", "Green Rhinocerous", "Purple Cow", "Yellow Cat", "Red Sloth")); deploy.addAll(Arrays.asList("Green Cow", "Green Cow", "Green Elephant", "Green Cow", "Green Cow", "Green Rhinocerous", "Purple Cow", "Yellow Cat", "Red Sloth", "Green Cow", "Purple Cow", "Green Cow", "Red Sloth", "Yellow Cat", "Green Rhinocerous", "Purple Cow")); rate.addAll(Arrays.asList(0.553683754016, 1.02150872447, 0.134625067987, 1.98664453833, 0.861269450714, 0.36946659851, 0.909230205525, 0.00248039618935, 0.160619970732, 0.545320579333, 0.0709241158945, 3.96782782573E-6, 0.849530002338, 1.29965105158, 6.72974424027E-6, 4.51463564725E-6)); // 用HashMap分组求和 Map<String, Double> costMap = new HashMap<>(); for (int j = 0; j < deploy.size(); j++) { String key = deploy.get(j); costMap.put(key, costMap.getOrDefault(key, 0.0) + rate.get(j)); } // 按singDeploy的顺序填充totCost for (String item : singDeploy) { totCost.add(costMap.getOrDefault(item, 0.0)); } // 验证结果 for (int i = 0; i < singDeploy.size(); i++) { System.out.println(singDeploy.get(i) + " 的总费用: " + totCost.get(i)); } } }
这个优化版本不仅效率更高,代码逻辑也更清晰,不容易出错。
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

