
本文详解如何从字符串中准确提取连续数字(如"abc10def21"中的10和21),而非单个字符,再按数值奇偶性分别求和;纠正常见误区(如误将ascii码当数字、错误使用scanner构造参数等),提供正则匹配与字符流两种专业实现方案。
本文详解如何从字符串中准确提取连续数字(如"abc10def21"中的10和21),而非单个字符,再按数值奇偶性分别求和;纠正常见误区(如误将ascii码当数字、错误使用scanner构造参数等),提供正则匹配与字符流两种专业实现方案。
在处理字符串中数字求和问题时,一个典型误区是将每个字符直接当作数字处理——例如 s.charAt(i) 返回的是 char 类型,其值为对应 ASCII 码(如 '5' 的 ASCII 值是 53),而非数字 5。原始代码中 Integer.parseInt(String.valueOf(temp)) 实际上是在解析 ASCII 数值的字符串表示(如把 53 转成整数 53),导致结果严重失真。此外,new Scanner("System.in") 创建的是以字面量 "System.in" 为内容的扫描器,而非读取标准输入,这是另一个关键错误。
要真正解决“提取字符串中所有完整数字并按奇偶分类求和”,需区分两种语义场景:
✅ 场景一:提取连续数字子串(推荐,符合题意“numbers in a string”)
例如输入 "abc10def21 ghij49sks12",应识别出 10、21、49、12 四个整数,再分别累加奇数(21 + 49 = 70)和偶数(10 + 12 = 22)。
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public class NumberSumByParity {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in); // ✅ 修正:从控制台读取
String s = sc.nextLine().trim();
Map<String, Integer> result = Pattern.compile("\d+")
.matcher(s)
.results()
.map(match -> Integer.parseInt(match.group()))
.collect(Collectors.groupingBy(
num -> num % 2 == 0 ? "Sum of Evens" : "Sum of Odds",
Collectors.reducing(0, Integer::sum)
));
System.out.println(result.get("Sum of Evens") + " " + result.get("Sum of Odds"));
// 输出示例:22 70(对应 10+12 和 21+49)
}
}✅ 场景二:仅对单个数字字符求和(即统计所有 '0'–'9' 字符对应的数值)
若需求是“字符串中每个数字字符(如 '3'、'8')本身作为一位数参与奇偶判断”,则无需正则,可直接流式处理字符:
Map<String, Integer> digitSums = s.chars()
.filter(Character::isDigit)
.mapToObj(c -> c - '0') // ✅ 安全转为数字值:'5' → 53 - 48 = 5
.collect(Collectors.groupingBy(
d -> d % 2 == 0 ? "Sum of Evens" : "Sum of Odds",
Collectors.summingInt(Integer::intValue)
));⚠️ 关键注意事项:
- 永远避免
Integer.parseInt(String.valueOf(char))对非数字字符或 ASCII 值操作; - 使用
c - '0'是将数字字符转为对应整数的高效安全方式; - 正则
\d+匹配一个或多个连续数字,精准捕获多位数(如"100"),而\d仅匹配单个数字; -
Collectors.reducing(0, Integer::sum)或Collectors.summingInt()均可实现累加,后者更简洁直观。
综上,正确解法的核心在于语义理解:题目中的 “numbers” 指逻辑意义上的整数(可能多位),而非字符层面的 digit。选择正则提取 + 流式分组,既健壮又符合工程实践,是 Java 8+ 环境下的推荐方案。

















