Stream で処理する正規表現

Java8 でも使えるように書いてみた。。

昨日の、 正規表現マッチのストリーム処理を考察 - Oboe吹きプログラマの黙示録
に続いて、思いついたので、まとめてみた。

import java.util.Iterator;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.Spliterators.AbstractSpliterator;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
 * RegExpress.java
 */
public final class RegExpress{
   private RegExpress(){
   }

   public static Stream<String> matchToStream(String regex, CharSequence input){
      Matcher m = Pattern.compile(regex).matcher(input);
      return StreamSupport.stream(Spliterators.spliteratorUnknownSize(new Iterator<String>(){
         @Override
         public boolean hasNext(){
            return m.find();
         }
         @Override
         public String next(){
            return m.group();
         }
      }, Spliterator.ORDERED), false);
   }

   public static Stream<MatchResult> findMatches(String regex, CharSequence input){
      Matcher matcher = Pattern.compile(regex).matcher(input);
      Spliterator<MatchResult> spliterator
= new AbstractSpliterator<MatchResult>(Long.MAX_VALUE, Spliterator.ORDERED | Spliterator.NONNULL){
         @Override
         public boolean tryAdvance(Consumer<? super MatchResult> action){
            if (!matcher.find())
               return false;
            action.accept(matcher.toMatchResult());
            return true;
         }
      };
      return StreamSupport.stream(spliterator, false);
   }

   public static void results(String regex, String input, Consumer<String> c){
      Matcher m = Pattern.compile(regex).matcher(input);
      while(m.find()){
         c.accept(m.group());
      }
   }

   public static void resultMatch(String regex, String input, Consumer<MatchResult> c){
      Matcher m = Pattern.compile(regex).matcher(input);
      while(m.find()){
         c.accept(m.toMatchResult());
      }
   }

   public static void resultMatch(String regex, String input, BiConsumer<MatchResult, Integer> c){
      Matcher m = Pattern.compile(regex).matcher(input);
      AtomicInteger i = new AtomicInteger(0);
      while(m.find()){
         c.accept(m.toMatchResult(), i.getAndIncrement());
      }
   }

   public static String replace(String regex, String string, BiFunction<String, Integer, String> f){
      Matcher m = Pattern.compile(regex).matcher(string);
      AtomicInteger i = new AtomicInteger(0);
      AtomicInteger x = new AtomicInteger(0);
      return StreamSupport.stream(Spliterators.spliteratorUnknownSize(new Iterator<String>(){
         @Override
         public boolean hasNext(){
            return m.find();
         }
         @Override
         public String next(){
            return string.substring(i.getAndSet(m.end()), m.start())
                    + f.apply(m.group(), x.getAndIncrement());
         }
      }, Spliterator.ORDERED), false).collect(Collectors.joining()) + string.substring(i.get());
   }
}

使用例

RegExpress.matchToStream("[0-9]+", string).forEach(e->System.out.println("["+e+"]"));

RegExpress.findMatches("[0-9]+", string)
.forEach(m->System.out.println("["+m.group()+"] start="+m.start()+" end="+m.end()));

RegExpress.resultMatch("[0-9]+", string, m->{
   System.out.println("["+m.group()+"] start="+m.start()+" end="+m.end());
});

RegExpress.resultMatch("[0-9]+", string, (m, i)->{
   System.out.println(i+":["+m.group()+"] start="+m.start()+" end="+m.end());
});

String res = RegExpress.replace("[0-9]+", string, (e, i)->"{"+i+":"+e+"}");