diff --git a/src/share/classes/java/util/regex/Pattern.java b/src/share/classes/java/util/regex/Pattern.java index 1dc72c10cd32a1df9ca27c6bf1482130029302cd..81ea7145a786a12693f459c590a81fdeae2cc6b3 100644 --- a/src/share/classes/java/util/regex/Pattern.java +++ b/src/share/classes/java/util/regex/Pattern.java @@ -5755,7 +5755,8 @@ NEXT: while (i <= last) { * 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. + * input. Trailing empty strings will be discarded and not encountered in + * the stream. * *
If this pattern does not match any subsequence of the input then
* the resulting stream has just one element, namely the input sequence in
@@ -5781,6 +5782,8 @@ NEXT: while (i <= last) {
private int current;
// null if the next element, if any, needs to obtained
private String nextElement;
+ // > 0 if there are N next empty elements
+ private int emptyElementCount;
MatcherIterator() {
this.matcher = matcher(input);
@@ -5790,26 +5793,46 @@ NEXT: while (i <= last) {
if (!hasNext())
throw new NoSuchElementException();
- String n = nextElement;
- nextElement = null;
- return n;
+ if (emptyElementCount == 0) {
+ String n = nextElement;
+ nextElement = null;
+ return n;
+ } else {
+ emptyElementCount--;
+ return "";
+ }
}
public boolean hasNext() {
- if (nextElement != null)
+ if (nextElement != null || emptyElementCount > 0)
return true;
if (current == input.length())
return false;
- if (matcher.find()) {
+ // Consume the next matching element
+ // Count sequence of matching empty elements
+ while (matcher.find()) {
nextElement = input.subSequence(current, matcher.start()).toString();
current = matcher.end();
+ if (!nextElement.isEmpty()) {
+ return true;
+ } else {
+ emptyElementCount++;
+ }
+ }
+
+ // Consume last matching element
+ nextElement = input.subSequence(current, input.length()).toString();
+ current = input.length();
+ if (!nextElement.isEmpty()) {
+ return true;
} else {
- nextElement = input.subSequence(current, input.length()).toString();
- current = input.length();
+ // Ignore a terminal sequence of matching empty elements
+ emptyElementCount = 0;
+ nextElement = null;
+ return false;
}
- return true;
}
}
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
diff --git a/test/java/util/regex/PatternTest.java b/test/java/util/regex/PatternStreamTest.java
similarity index 82%
rename from test/java/util/regex/PatternTest.java
rename to test/java/util/regex/PatternStreamTest.java
index aab17319ae41288fb6453461a4fe79592216a6ab..374b62378e9726bd129b87e29a17310e6fe90490 100644
--- a/test/java/util/regex/PatternTest.java
+++ b/test/java/util/regex/PatternStreamTest.java
@@ -23,10 +23,11 @@
/**
* @test
+ * @bug 8016846 8024341
* @summary Unit tests for wrapping classes should delegate to default methods
* @library ../stream/bootlib
* @build java.util.stream.OpTestCase
- * @run testng/othervm PatternTest
+ * @run testng/othervm PatternStreamTest
*/
import org.testng.annotations.DataProvider;
@@ -42,7 +43,7 @@ import java.util.stream.Stream;
import java.util.stream.TestData;
@Test
-public class PatternTest extends OpTestCase {
+public class PatternStreamTest extends OpTestCase {
@DataProvider(name = "Stream