简体   繁体   English

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

[英]Java 8 removing an item from array/array list based on regex

Is there a better way to achieve the following in java 8? 有没有更好的方法来实现java 8中的以下内容?

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

You can use 您可以使用

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

You could also use the simpler 你也可以使用更简单的

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

but it will perform Pattern.compile("^SACHI") under the hood, for every element in the worst case. 但它会在最糟糕的情况下为每个元素执行Pattern.compile("^SACHI") Note that the Pattern created by compile is immutable and can be shared, hence, you could also create it only once, like 请注意,通过compile创建的Pattern是不可变的并且可以共享,因此,您也可以只创建一次,例如

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

and use it like 并使用它

personalNames.removeIf(REMOVAL_PATTERN.asPredicate());

asPredicate() uses find() instead of matches() , but since your pattern has the ^ anchor, it makes no difference. asPredicate()使用find()而不是matches() ,但由于你的模式有^锚,因此没有区别。 The method asMatchPredicate() for getting a predicate using matches() has been added in JDK 11. 在JDK 11中添加了使用matches()获取谓词的方法asMatchPredicate()


If all you want, is to match a literal string at the beginning, you can also use 如果你想要的只是在开头匹配一个文字字符串,你也可以使用

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

which does not have the regex initialization overhead. 它没有正则表达式初始化开销。

Adding and/or removing elements from an existing container does not fit in nicely with the concepts of functional programming. 从现有容器添加和/或删除元素不能很好地适应函数式编程的概念。 More over that behavior is not thread safe in parallel and concurrent environment. 更多关于该行为在并行和并发环境中不是线程安全的。 Making it thread safe demands more effort too. 使其线程安全也需要更多的努力。 Therefore prefer steteless lambdas to stateful lambdas as a good engineering practice. 因此,作为一种良好的工程实践,更喜欢无耻的lambdas到有状态的lambdas。 You can get the matching names by merely using filter operator. 您只需使用过滤器运算符即可获得匹配的名称。 Here's how it looks. 这是它的外观。

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

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

It depends did you need to modify existing list, or you need just get list without elements. 这取决于您是否需要修改现有列表,或者只需要获取没有元素的列表。 In first case, you can use stream to filter non matching objects and remove them from list 在第一种情况下,您可以使用流过滤非匹配对象并从列表中删除它们

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

In other case, you can just return new list with only matching objects 在其他情况下,您只需返回仅包含匹配对象的新列表

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

also, this code 还有,这段代码

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

will throw java.util.ConcurrentModificationException 将抛出java.util.ConcurrentModificationException

You can extract errorProneNames by filtering and removing respective error names from personalNames iterating forEach : 您可以通过filtering并从personalNames迭代forEach删除相应的错误名称来提取errorProneNames

List<String> errorProneNames = personalNames.stream()
        .filter(name -> !name.matches(regex))
        .collect(Collectors.toList());

errorProneNames.forEach(personalNames::remove);

They are equivalent: 他们是等价的:

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

and

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

Using Predicate<T> to filter out the names which do not matches to String regex . 使用Predicate<T>过滤掉与String regex不匹配的名称。 test(T t) evaluates this predicate on the given argument. test(T t)根据给定的参数计算此谓词。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM