在java数组列表中搜索regexp

zqry0prt  于 2023-04-04  发布在  Java
关注(0)|答案(8)|浏览(98)
ArrayList <String> list = new ArrayList(); 
list.add("behold");
list.add("bend");
list.add("bet");
list.add("bear");
list.add("beat");
list.add("become");
list.add("begin");

有一种方法可以搜索正则表达式bea.* 并获得索引,就像ArrayList.indexOf?
编辑:返回的项目是好的,但我需要的东西与更多的性能比线性搜索

omjgkv6w

omjgkv6w1#

Herms基本上是正确的。如果你想要String而不是索引,那么你可以通过使用Java 5 foreach循环来改进:

import java.util.regex.Pattern;
import java.util.ListIterator;
import java.util.ArrayList;

/**
 * Finds the index of all entries in the list that matches the regex
 * @param list The list of strings to check
 * @param regex The regular expression to use
 * @return list containing the indexes of all matching entries
 */
List<String> getMatchingStrings(List<String> list, String regex) {

  ArrayList<String> matches = new ArrayList<String>();

  Pattern p = Pattern.compile(regex);

  for (String s:list) {
    if (p.matcher(s).matches()) {
      matches.add(s);
    }
  }

  return matches
}
8aqjt8rx

8aqjt8rx2#

有内置的方法吗?据我所知没有。但是,自己做应该很容易。下面是一些完全未经测试的代码,应该给予你基本的想法:

import java.util.regex.Pattern;
import java.util.ListIterator;
import java.util.ArrayList;

/**
 * Finds the index of all entries in the list that matches the regex
 * @param list The list of strings to check
 * @param regex The regular expression to use
 * @return list containing the indexes of all matching entries
 */
List<Integer> getMatchingIndexes(List<String> list, String regex) {
  ListIterator<String> li = list.listIterator();

  List<Integer> indexes = new ArrayList<Integer>();

  while(li.hasNext()) {
    int i = li.nextIndex();
    String next = li.next();
    if(Pattern.matches(regex, next)) {
      indexes.add(i);
    }
  }

  return indexes;
}

我可能对Pattern和ListIterator部分的用法有一点错误(我从来没有使用过这两个部分),但这应该给予了基本的想法。

vybvopom

vybvopom3#

一种选择是使用Apache Commons CollectionUtils“select”方法。您需要创建一个Predicate对象(具有单个“evaluate”方法的对象,该方法使用正则表达式检查匹配并返回true或false),然后您可以在列表中搜索匹配的项。但是,它不会返回索引,它将返回包含项本身的集合。

mo49yndu

mo49yndu4#

这是Guava中的一条线:

final Iterable<String> matches = Iterables.filter(myStrings, Predicates.contains(Pattern.compile("myPattern")));

for (final String matched : matches) {
   ...
}
mum43rcc

mum43rcc5#

我不相信有一个Java API的方法来做这件事,也没有一个Apache Commons的方法来做这件事。

cyvaqqii

cyvaqqii6#

这将是一个线程复兴,但可能对某些人有用。你可能不需要索引,可能下一步会对匹配正则表达式的项目做一些事情,因此你要求索引。但你可以使用Java8流和lambda表达式:

import java.util.regex.Pattern;
  import java.util.stream.Collectors;
  import java.util.List;

  ...

  var pattern = Pattern.compile(define);  // var is Java 10 feature

  List<String> list = originalList
      .stream()
      .filter(e -> pattern.matcher(e).matches())
      .collect(Collectors.toList());

你可以获取原始列表,将其转换为流,在其上运行一个过滤器,该过滤器运行lambda来匹配你的模式,并将其转换回列表。但你可以将其保持为流,并使用另一个lambda表达式在其上运行.foreach。

u4vypkhs

u4vypkhs7#

当我们讨论大型列表时,将它们与Java8内置函数并行传输是有意义的。

@Test
public void testRegexPerformance()
{
    List<String> list = new ArrayList<>();
    list.add("behold");
    list.add("bend");
    list.add("bet");
    list.add("bear");
    list.add("beat");
    list.add("become");
    list.add("begin");
    for (int i = 0; i < 20; i++)
    {
        list.addAll(list);
    }
    System.out.println("Original list size: " + list.size());
    Instant startTime = Instant.now();
    List<String> results = testLoopApproach(list, "bea.*");
    Instant current = Instant.now();
    System.out.println("Found List size: " + results.size());
    System.out.println("Elapsed millis: " + (current.toEpochMilli() - startTime.toEpochMilli()));
    startTime = Instant.now();
    results = testStreamApproach(list, "bea.*");
    current = Instant.now();
    System.out.println("Found List size: " + results.size());
    System.out.println("Elapsed millis: " + (current.toEpochMilli() - startTime.toEpochMilli()));
}

private List<String> testStreamApproach(List<String> list, String regex)
{
    Predicate<String> pred = Pattern.compile(regex).asPredicate();
    return list.parallelStream().filter(pred).collect(Collectors.toList());
}

private List<String> testLoopApproach(List<String> list, String regex)
{
    Pattern p = Pattern.compile(regex);
    List<String> resulsts = new ArrayList<>();
    for (String string : list)
    {
        if (p.matcher(string).find())
        {
            resulsts.add(string);
        }
    }
    return resulsts;
}

and the results are:
Original list size: 7340032
Found List size: 2097152
Elapsed millis: 1785
Found List size: 2097152
Elapsed millis: 260
irlmq6kh

irlmq6kh8#

这里是一个线性复杂度的答案,使用一个简单的for循环,它让你可以选择返回索引或单词!

ArrayList<String> wordList = new ArrayList<String>(Arrays.asList("behold", "bend", "bet", "bear", "beat", "become", "begin"));
for (int i = 0; i < wordList.size(); i++) {
  String word = wordList.get(i);
  if (word.matches("bea.*")) {
    System.out.println("index for " + word + " is: " + i);
  }
}

如前所述,除非您知道列表的排序,否则无法比线性搜索做得更好,

相关问题