You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用正则表达式与Predicate过滤Stream流以获取不符合规则的城市名列表

解决城市名非法字符筛选问题

看起来你在筛选含非法字符的城市名时,因为正则表达式的逻辑偏差,导致结果和预期完全相反。咱们来拆解问题并修复它:

问题根源:当前正则的逻辑错误

你现在用的正则[^a-z0-9-]*$,意思是字符串结尾有0个或多个非法字符。但*允许匹配0次,这意味着所有完全合法的城市名(没有任何非法字符)也会被这个规则匹配到,所以filter会把所有城市都放进invalidCharactersList,这就是为什么第一个全合法的列表也触发了异常。

两种正确的实现方案

方案1:直接匹配含非法字符的城市名

我们需要一个能匹配至少包含一个非法字符的正则,正确写法是.*[^a-z0-9-].*,它的逻辑是:

  • .*:匹配任意数量的任意字符(开头部分)
  • [^a-z0-9-]:精准匹配一个不在允许范围内的字符(核心的非法检测)
  • .*:匹配任意数量的任意字符(结尾部分)

修改后的代码:

String str;
List<String> invalidCharactersList = cityName.stream()
    .filter(Pattern.compile(".*[^a-z0-9-].*").asPredicate())
    .collect(Collectors.toList());

// 检查非法名称
if (!invalidCharactersList.isEmpty()) {
    str = (inOut) ? "c" : "q";
    throw new IllegalArgumentException("City name characters " + str + ": for city name " + invalidCharactersList.get(0) + ": fails constraint city names [a-z, 0-9, -]");
}

方案2:先匹配合法城市名,再取反

另一种更直观的思路:先定义“合法城市名”的规则,再筛选出不满足这个规则的城市。合法城市名的正则是^[a-z0-9-]+$,含义是:

  • ^:字符串开头
  • [a-z0-9-]+:匹配至少一个允许的字符(a-z、0-9、-)
  • $:字符串结尾

然后用negate()把规则取反,就得到了非法城市名的筛选条件:

String str;
List<String> invalidCharactersList = cityName.stream()
    .filter(Pattern.compile("^[a-z0-9-]+$").asPredicate().negate())
    .collect(Collectors.toList());

// 检查非法名称
if (!invalidCharactersList.isEmpty()) {
    str = (inOut) ? "c" : "q";
    throw new IllegalArgumentException("City name characters " + str + ": for city name " + invalidCharactersList.get(0) + ": fails constraint city names [a-z, 0-9, -]");
}

测试验证

用你提供的测试列表q = Arrays.asList("fastcity*", "bigbanana", "xyz&"),两种方案都会把"fastcity*"和"xyz&"筛选进invalidCharactersList,触发异常,完全符合你的预期;而全合法的列表c会让invalidCharactersList为空,不会抛出异常。

内容的提问来源于stack exchange,提问作者charlie f

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 10:52:33