Java 8基于正则表达式从数组/数组列表中删除项目

时间:2019-02-21 08:21:43

标签: java java-8

在Java 8中是否有更好的方法来实现以下目标?

String regex = "^SACHI";
for (String temp : personalNames ) {
    if (temp.matches(regex)){
         personalNames.remove(temp);
    }
}

6 个答案:

答案 0 :(得分:8)

您可以使用

personalNames.removeIf(Pattern.compile("^SACHI").asPredicate());

您也可以使用更简单的

personalNames.removeIf(s -> s.matches("^SACHI"));

,但对于最坏情况下的每个元素,它都会在后台执行Pattern.compile("^SACHI")。请注意,由Pattern创建的compile是不可变的,可以共享,因此,您也只能创建一次,例如

static final Pattern REMOVAL_PATTERN = Pattern.compile("^SACHI");

并像使用它

personalNames.removeIf(REMOVAL_PATTERN.asPredicate());

asPredicate()使用find()而不是matches(),但是由于您的模式具有^锚点,因此没有区别。在JDK 11中添加了使用asMatchPredicate()获取谓词的方法matches()


如果只想在开头匹配文字字符串,也可以使用

personalNames.removeIf(s -> s.startsWith("SACHI"));

没有regex初始化开销。

答案 1 :(得分:3)

从现有容器中添加和/或删除元素与函数式编程的概念不太吻合。此外,这种行为在并行和并发环境中不是线程安全的。使线程安全也需要更多的努力。因此,作为一种良好的工程实践,将无Stef Lambda优先于有状态Lambda。您只需使用过滤器运算符就可以获取匹配的名称。看起来就是这样。

private static final Pattern PATTERN = Pattern.compile("^SACHI");

List<String> validNames = personalNames.stream()
    .filter(PATTERN.asPredicate())
    .collect(Collectors.toList());

答案 2 :(得分:2)

这取决于您需要修改现有列表,还是只需要获取不包含元素的列表。 在第一种情况下,您可以使用流过滤不匹配的对象并将其从列表中删除

personalNames.removeAll(
        personalNames
                .stream()
                .filter(x -> !x.matches(regex))
                .collect(Collectors.toList())
);

在其他情况下,您可以仅返回仅包含匹配对象的新列表

final List<String> matchingElements = personalNames.stream()
        .filter(x -> x.matches(regex))
        .collect(Collectors.toList());

此代码

for (String temp : personalNames ) {
    if (temp.matches(regex)){
        personalNames.remove(temp);
    }
}

会抛出 java.util.ConcurrentModificationException

答案 3 :(得分:1)

您可以通过errorProneNames提取filtering并从迭代personalNames的{​​{1}}中删除相应的错误名称:

forEach

答案 4 :(得分:1)

它们等效:

for (String temp : personalNames ) {
   if (temp.matches(regex)){
     personalNames.remove(temp);
   }
}

personalNames.removeIf(name -> name.matches(regex));

答案 5 :(得分:0)

   String regex = "^SACHI";
   Predicate<String> f = n-> n.matches(regex);
   personalNames.stream().filter(x->f.test(x))
                         .forEach(n-> {
                          personalNames.remove(n);
                          });

使用Predicate<T>筛选出与String regex不匹配的名称。 test(T t) 根据给定参数评估该谓词。