Найти регулярное выражение в java arraylist

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"); 

Есть способ поиска regexp bea. * и получить индексы, как в ArrayList.indexOf?

EDIT: возврат элементов в порядке, но мне нужно что-то с большей производительностью, чем линейный поиск

Ответы

Ответ 1

Хермс правильно понял основы. Если вам нужны строки, а не индексы, то вы можете улучшить, используя цикл foreach Java 5:

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
}

Ответ 2

Есть ли встроенный метод? Не то, что я знаю из. Тем не менее, это должно быть довольно легко сделать это самостоятельно. Вот некоторый полностью непроверенный код, который должен дать вам основную идею:

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 (я тоже никогда не использовал), но это должно дать основную идею. Вы также можете сделать простой цикл for вместо цикла while над итератором.

Ответ 3

Одним из вариантов является использование метода "выбора" Apache Commons CollectionUtils. Вам нужно будет создать объект Predicate (объект с единственным методом "оценки", который использует регулярное выражение для проверки на совпадение и возвращает true или false), а затем вы можете искать элементы в списке, которые соответствуют. Однако он не возвращает индексы, он возвращает коллекцию, содержащую сами элементы.

Ответ 4

Это один лайнер в guava:

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

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

Ответ 5

Я не верю, что есть способ Java API для этого, и нет способа сделать это Apache Commons. Это не составит труда сворачивать ваши собственные.

Ответ 6

Это возродит нить, но может быть кому-то полезно. Вам могут не понадобиться индексы, возможно, следующий шаг что-то сделает с элементами, которые соответствуют регулярному выражению, и поэтому вы запросили индексы. Но вы можете использовать потоки Java8 и лямбда-выражения:

  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());

Вы можете взять исходный список, преобразовать его в поток, запустить на нем фильтр, который запускает лямбду, чтобы соответствовать вашему шаблону, и преобразовать его обратно в список. Но вы можете сохранить его как поток и запустить .foreach на нем с другим лямбда-выражением.