changeset 7838:526131346981

Pattern.splitAsStream. Contributed-by: Ben Evans <benjamin.john.evans@gmail.com>
author psandoz
date Mon, 08 Apr 2013 17:16:36 +0200
parents 0309ea20fc21
children 3d940b4308ee
files src/share/classes/java/util/regex/Pattern.java test-ng/tests/org/openjdk/tests/java/util/regex/PatternTest.java
diffstat 2 files changed, 202 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/util/regex/Pattern.java	Mon Apr 08 16:05:54 2013 +0200
+++ b/src/share/classes/java/util/regex/Pattern.java	Mon Apr 08 17:16:36 2013 +0200
@@ -30,10 +30,18 @@
 import java.text.CharacterIterator;
 import java.text.Normalizer;
 import java.util.Locale;
+import java.util.Iterator;
 import java.util.Map;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Arrays;
+import java.util.NoSuchElementException;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+import java.util.stream.Streams;
 
 
 /**
@@ -5741,4 +5749,93 @@
                     return Character.isMirrored(ch);}});
         }
     }
+
+    /**
+     * Creates a predicate which can be used to match a string.
+     *
+     * @return  The predicate which can be used for matching on a string
+     * @since       1.8
+     *
+     */
+    public Predicate<String> asPredicate(){
+        return s -> this.matcher(s).find();
+    }
+
+    private static class MatcherIterator implements Iterator<String> {
+	private final Matcher curMatcher;
+        private final CharSequence input;
+	private int current = 0;
+        private String nextElement = null;
+	private boolean valueReady = false;
+        
+	MatcherIterator(CharSequence in, Matcher m) {
+	    input = in;
+	    curMatcher = m;
+	}
+
+	public void accept(String t) {
+	    valueReady = true;
+	    nextElement = t;
+	}
+	
+	public String next() {
+	    if (!valueReady && !hasNext())
+		throw new NoSuchElementException();
+	    else {
+		valueReady = false;
+		return nextElement;
+	    }
+	}
+
+	public boolean hasNext() {
+	    if (!valueReady) {
+		if (current == input.length()) return false;
+
+		if (curMatcher.find()) {
+		    nextElement = input.subSequence(current, curMatcher.start()).toString();
+		    current = curMatcher.end();
+		    valueReady = true;
+		} else {
+		    nextElement = input.subSequence(current, input.length()).toString();
+		    current = input.length();
+		    valueReady = true;
+		}
+	    }
+	    return true;
+	}
+    }
+
+
+    /**
+     * Creates a stream from the given input sequence around matches of this 
+     * pattern.
+     *
+     * <p>The stream returned by this method contains each substring of the
+     * input sequence that is terminated by another subsequence that matches
+     * this pattern or is terminated by the end of the input sequence.  The
+     * substrings in the stream are in the order in which they occur in the
+     * input.  
+     *
+     * <p>If this pattern does not match any subsequence of the input then
+     * the resulting stream has just one element, namely the input sequence in
+     * string form.
+     *
+     * <p>If the input sequence is mutable, it must remain constant during the
+     * execution of the terminal stream operation.  Otherwise, the result of the
+     * terminal stream operation is undefined.
+     *
+     * @see     #split(CharSequence)
+     *
+     * @param   input
+     *          The character sequence to be split
+     *
+     * @return  The stream of strings computed by splitting the input
+     *          around matches of this pattern
+     * @since   1.8
+     * 
+     */
+    public Stream<String> splitAsStream(final CharSequence input) {
+	return Streams.stream(Spliterators.spliteratorUnknownSize(new MatcherIterator(input, matcher(input)), 
+								  Spliterator.ORDERED | Spliterator.NONNULL));
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-ng/tests/org/openjdk/tests/java/util/regex/PatternTest.java	Mon Apr 08 17:16:36 2013 +0200
@@ -0,0 +1,105 @@
+package org.openjdk.tests.java.util.regex;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Functions;
+import java.util.function.Supplier;
+import java.util.regex.Pattern;
+import java.util.stream.OpTestCase;
+import java.util.stream.Stream;
+import java.util.stream.StreamTestData;
+import java.util.stream.Streams;
+
+import static java.util.stream.Collectors.toList;
+
+@Test
+public class PatternTest extends OpTestCase {
+
+    @DataProvider(name = "Stream<String>")
+    public static Object[][] makeStreamTestData() {
+        List<Object[]> data = new ArrayList<>();
+
+	String description = "";
+	String input = "awgqwefg1fefw4vssv1vvv1";
+	Pattern pattern = Pattern.compile("4");
+	List<String> expected = new ArrayList<>();
+	expected.add("awgqwefg1fefw");
+	expected.add("vssv1vvv1");
+
+	// Must match the type signature of the consumer of this data, testStrings
+	// String, String, Pattern, List<String>
+	data.add(new Object[]{description, input, pattern, expected});
+
+	input = "afbfq\u00a3abgwgb\u00a3awngnwggw\u00a3a\u00a3ahjrnhneerh";
+	pattern = Pattern.compile("\u00a3a");
+	expected = new ArrayList<>();
+	expected.add("afbfq");
+	expected.add("bgwgb");
+	expected.add("wngnwggw");
+	expected.add("");
+	expected.add("hjrnhneerh");
+
+	data.add(new Object[]{description, input, pattern, expected});
+
+
+	input = "awgqwefg1fefw4vssv1vvv1";
+	pattern = Pattern.compile("1");
+	expected = new ArrayList<>();
+	expected.add("awgqwefg");
+	expected.add("fefw4vssv");
+	expected.add("vvv");
+
+	data.add(new Object[]{description, input, pattern, expected});
+
+
+	input = "a\u4ebafg1fefw\u4eba4\u9f9cvssv\u9f9c1v\u672c\u672cvv";
+	pattern = Pattern.compile("1");
+	expected = new ArrayList<>();
+	expected.add("a\u4ebafg");
+	expected.add("fefw\u4eba4\u9f9cvssv\u9f9c");
+	expected.add("v\u672c\u672cvv");
+
+	data.add(new Object[]{description, input, pattern, expected});
+
+
+	input = "1\u56da23\u56da456\u56da7890";
+	pattern = Pattern.compile("\u56da");
+	expected = new ArrayList<>();
+	expected.add("1");
+	expected.add("23");
+	expected.add("456");
+	expected.add("7890");
+
+	data.add(new Object[]{description, input, pattern, expected});
+
+
+	input = "1\u56da23\u9f9c\u672c\u672c\u56da456\u56da\u9f9c\u672c7890";
+	pattern = Pattern.compile("\u56da");
+	expected = new ArrayList<>();
+	expected.add("1");
+	expected.add("23\u9f9c\u672c\u672c");
+	expected.add("456");
+	expected.add("\u9f9c\u672c7890");
+
+	data.add(new Object[]{description, input, pattern, expected});
+
+
+	input = "";
+	pattern = Pattern.compile("\u56da");
+	expected = new ArrayList<>();
+
+	data.add(new Object[]{description, input, pattern, expected});
+
+        return data.toArray(new Object[0][]);
+    }
+
+    @Test(dataProvider = "Stream<String>")
+    public void testStrings(String description, String input, Pattern pattern, List<String> expected) {
+	Supplier<Stream<String>> ss =  () -> pattern.splitAsStream(input);
+	withData(new StreamTestData.StreamSupplierData<>(description, ss))
+		 .stream(Functions.identity()).expectedResult(expected).exercise();
+    }
+}