Функциональный стиль java.util.regex соответствие / извлечение группы - PullRequest
6 голосов
/ 09 июня 2019

Используя java.util.regex для извлечения подстрок, я обнаружил, что реализую тот же шаблон кода, работая с вызовами:

Pattern p = Pattern.compile(pattern); // can be static final
Matcher m = p.matcher(input);
if (m.find()) { // or m.matches()
    foo(m.group(x));
} else {
    ...
}

Существует ли функциональное расширение или популярная библиотека (guava / apache commons), которая позволяет избежать уродливых ненужных и подверженных ошибкам локальных переменных, например:

Pattern p = Pattern.compile(pattern); // can be static final
p.matchedGroup(input, x) // return Optional<String>
    .map(group -> foo(group))
    .orElse(...);

, а также поток результатов матчей, таких как:

Pattern p = Pattern.compile(pattern);
p.findMatches(input)
    .map((MatchResult mr) -> {
        mr.groupsIfPresent(x).map(g -> foo(g)).orElse(...)
    })
    .findFirst();

Кажется, единственным функциональным дополнением в Java8 было .splitAsStream(), но это помогает только при попытке разбить совпадения.

Ответы [ 2 ]

6 голосов
/ 09 июня 2019

Следующее доступно только от

Вы, вероятно, ищете Matcher::results, который производит Stream<MatchResult>

Вы можете использовать его следующим образом, например

p.matcher(input)
 .results()
 .map(MatchResult::group)
 .findAny()
 .orElse(null);

Добавление, добавленное Holger и представляющее интерес, будет при чтении File и поиске шаблона для непосредственного использования Scanner::findAll, чтобы избежать загрузки всего файла в памяти с помощью File::lines

6 голосов
/ 09 июня 2019

Существует элегантное решение, которое работает как для Stream<String>, так и для Optional<String>:

    Pattern pattern = Pattern.compile("...");

    List<String> input = new ArrayList<>();

    List<String> matches = input.stream()
            .map(pattern::matcher)
            .filter(Matcher::find)
            .map(m -> m.group(x))
            .collect(Collectors.toList());

Хотя я хотел бы отметить, что выполнение операции изменения / изменения в вызове filterнеобычноПожалуйста, будьте осторожны при выполнении мутаций в вызовах filter и избегайте их в максимально возможной степени.В этом случае, хотя (с моей субъективной точки зрения) это нормально, когда вы изменяете объект, который вы только что создали в потоке, который не используется вне операций потока.

Используйте Optional.ofNullable/of, когда у вас есть только один входвсе остальное выглядит так же.

...