changeset 7176:404ba8d46d50

Functional tests for java.util.stream Tests for Atomicxxx's updateAndGet()/getAndUpdate() Tests for new added Map default's methods Tests for new added List default's methods Tests for Arrays.parallelPrefixxxx() Tests for Collection.removeAll()/forEach() Tests for String's operation Sanity tests for support reducers Contributed-by: Tristan Yan <tristan.yan@oracle.com>
author mdugiou
date Sun, 27 Jan 2013 12:55:52 -0800
parents 0e769b2115cc
children 62b653dba473
files test/java/lang/Byte/ByteReducersTest.java test/java/lang/Character/CharacterReducersTest.java test/java/lang/Double/DoubleReducersTest.java test/java/lang/Float/FloatReducersTest.java test/java/lang/Integer/IntegerReducersTest.java test/java/lang/Long/LongReducersTest.java test/java/lang/Short/ShortReducersTest.java test/java/lang/String/JoinTest.java test/java/lang/StringBuilder/AddAllTest.java test/java/util/Arrays/ParallelPrefixTest.java test/java/util/Collection/IntRemovePredicateAllTest.java test/java/util/LambdaUtilities.java test/java/util/List/ExtensionsTest.java test/java/util/Map/LambdaTest.java test/java/util/StringJoiner/BasicTest.java test/java/util/StringUtilities.java test/java/util/concurrent/AtomicInteger/UpdateAndGetTest.java test/java/util/concurrent/AtomicIntegerFieldUpdater/UpdateAndGetTest.java test/java/util/concurrent/AtomicLong/UpdateAndGetTest.java test/java/util/concurrent/AtomicLongFieldUpdater/UpdateAndGetTest.java test/java/util/concurrent/AtomicReference/UpdateAndGetTest.java test/java/util/concurrent/AtomicReferenceFieldUpdater/UpdateAndGetTest.java test/java/util/stream/Stream/EmployeeStreamTest.java test/java/util/stream/Stream/IntStreamTest.java test/java/util/stream/Stream/IntegerStreamTest.java test/java/util/stream/Stream/StringBuilderStreamTest.java test/java/util/stream/Streams/BasicTest.java
diffstat 27 files changed, 7605 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/Byte/ByteReducersTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary
+ * @(#) ByteReducersTest.java
+ * @author Tristan Yan
+ * @run testng ByteReducersTest
+ */
+
+import java.util.Random;
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+public class ByteReducersTest {
+    private final static int LOOP = (int)Byte.MAX_VALUE - (int)Byte.MIN_VALUE;
+
+    private final static Random rand = new Random(System.currentTimeMillis());
+
+    @Test
+    public void testMax() {
+        for(int index = 0; index < LOOP; index++){
+            byte b1 = (byte)(rand.nextInt() & 0xff);
+            byte b2 = (byte)(rand.nextInt() & 0xff);
+            byte expected = b1 > b2 ? b1 : b2;
+            assertEquals(Byte.max(b1, b2), expected);
+        }
+    }
+
+    @Test
+    public void testMin() {
+        for(int index = 0; index < LOOP; index++){
+            byte b1 = (byte)(rand.nextInt() & 0xff);
+            byte b2 = (byte)(rand.nextInt() & 0xff);
+            byte expected = b1 < b2 ? b1 : b2;
+            assertEquals(Byte.min(b1, b2), expected);
+        }
+    }
+
+    @Test
+    public void testSum() {
+        for(int index = 0; index < LOOP; index++){
+            byte b1 = (byte)(rand.nextInt() & 0xff);
+            byte b2 = (byte)(rand.nextInt() & 0xff);
+            byte expected = (byte)(b1 + b2);
+            assertEquals(Byte.sum(b1, b2), expected);
+        }
+    }
+
+    @Test
+    public void testUnsigned() {
+        for(int index = 0; index < LOOP; index++){
+            byte b = (byte)(rand.nextInt() & 0xff);
+            assertEquals(Byte.toUnsignedInt(b),
+                    (b < 0 ? (int)b + (int)Byte.MAX_VALUE - (int)Byte.MIN_VALUE + 1 : (int)b));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/Character/CharacterReducersTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary
+ * @(#) CharacterReducersTest.java
+ * @author Tristan Yan
+ * @run testng CharacterReducersTest
+ */
+
+import java.util.Random;
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+public class CharacterReducersTest {
+    private final static int LOOP = 1 << 20;
+
+    private final static Random rand = new Random(System.currentTimeMillis());
+
+    @Test
+    public void testMax() {
+        for(int index = 0; index < LOOP; index++){
+            char c1 = (char)(rand.nextInt() & 0xffff);
+            char c2 = (char)(rand.nextInt() & 0xffff);
+            char expected = c1 > c2 ? c1 : c2;
+            assertEquals(Character.max(c1, c2), expected);
+        }
+    }
+
+    public void testMin(char i, char j) {
+        for(int index = 0; index < LOOP; index++){
+            char c1 = (char)(rand.nextInt() & 0xffff);
+            char c2 = (char)(rand.nextInt() & 0xffff);
+            char expected = c1 < c2 ? c1 : c2;
+            assertEquals(Character.min(c1, c2), expected);
+        }
+    }
+
+    public void testSum(char i, char j) {
+        for(int index = 0; index < LOOP; index++){
+            char c1 = (char)(rand.nextInt() & 0xffff);
+            char c2 = (char)(rand.nextInt() & 0xffff);
+            char expected = (char)(c1 + c2);
+            assertEquals(Character.sum(c1, c2), expected);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/Double/DoubleReducersTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary
+ * @(#) DoubleReducersTest.java
+ * @author Tristan Yan
+ * @run testng DoubleReducersTest
+ */
+
+import java.util.Random;
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+public class DoubleReducersTest {
+    private final static int LOOP = 1 << 20;
+
+    private final static Random rand = new Random(System.currentTimeMillis());
+
+    @Test
+    public void testMax() {
+        for(int index = 0; index < LOOP; index++){
+            double d1 = rand.nextDouble();
+            double d2 = rand.nextDouble();
+            double expected = d1 > d2 ? d1 : d2;
+            assertEquals(Double.max(d1, d2), expected);
+        }
+    }
+
+    @Test
+    public void testMin() {
+        for(int index = 0; index < LOOP; index++){
+            double d1 = rand.nextDouble();
+            double d2 = rand.nextDouble();
+            double expected = d1 < d2 ? d1 : d2;
+            assertEquals(Double.min(d1, d2), expected);
+        }
+    }
+
+    @Test
+    public void testSum() {
+        for(int index = 0; index < LOOP; index++){
+            double d1 = rand.nextDouble();
+            double d2 = rand.nextDouble();
+            double expected = d1 + d2;
+            assertEquals(Double.sum(d1, d2), expected);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/Float/FloatReducersTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary
+ * @(#) FloatReducersTest.java
+ * @author Tristan Yan
+ * @run testng FloatReducersTest
+ */
+
+import java.util.Random;
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+public class FloatReducersTest {
+    private final static int LOOP = 1 << 20;
+
+    private final static Random rand = new Random(System.currentTimeMillis());
+
+    @Test
+    public void testMax() {
+        for(int index = 0; index < LOOP; index++){
+            float f1 = rand.nextFloat();
+            float f2 = rand.nextFloat();
+            float expected = f1 > f2 ? f1 : f2;
+            assertEquals(Float.max(f1, f2), expected);
+        }
+    }
+
+    @Test
+    public void testMin() {
+        for(int index = 0; index < LOOP; index++){
+            float f1 = rand.nextFloat();
+            float f2 = rand.nextFloat();
+            float expected = f1 < f2 ? f1 : f2;
+            assertEquals(Float.min(f1, f2), expected);
+        }
+    }
+
+    @Test
+    public void testSum() {
+        for(int index = 0; index < LOOP; index++){
+            float f1 = rand.nextFloat();
+            float f2 = rand.nextFloat();
+            float expected = f1 + f2;
+            assertEquals(Float.sum(f1, f2), expected);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/Integer/IntegerReducersTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary
+ * @(#) IntegerReducersTest.java
+ * @author Tristan Yan
+ * @run testng IntegerReducersTest
+ */
+
+import java.util.Random;
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+public class IntegerReducersTest {
+    private final static int LOOP = 1 << 20;
+
+    private final static Random rand = new Random(System.currentTimeMillis());
+
+    @Test
+    public void testMax() {
+        for(int index = 0; index < LOOP; index++){
+            int i1 = rand.nextInt();
+            int i2 = rand.nextInt();
+            int expected = i1 > i2 ? i1 : i2;
+            assertEquals(Integer.max(i1, i2), expected);
+        }
+    }
+
+    @Test
+    public void testMin() {
+        for(int index = 0; index < LOOP; index++){
+            int i1 = rand.nextInt();
+            int i2 = rand.nextInt();
+            int expected = i1 < i2 ? i1 : i2;
+            assertEquals(Integer.min(i1, i2), expected);
+        }
+    }
+
+    @Test
+    public void testSum() {
+        for(int index = 0; index < LOOP; index++){
+            int i1 = rand.nextInt();
+            int i2 = rand.nextInt();
+            int expected = i1 + i2;
+            assertEquals(Integer.sum(i1, i2), expected);
+        }
+    }
+
+    @Test
+    public void testUnsignedWithoutRadix(){
+        for(int index = 0; index < LOOP; index++){
+            int i = rand.nextInt();
+            assertEquals(Integer.parseUnsignedInt(Integer.toUnsignedString(i)), i);
+            assertEquals(Integer.toUnsignedString(i, 10), Integer.toUnsignedString(i));
+            if(i >= 0)
+                assertEquals(Integer.toUnsignedString(i), Integer.toString(i));
+        }
+    }
+
+    @Test
+    public void testUnsignedWithRadix(){
+        for(int index = 0; index < LOOP; index++){
+            int i = rand.nextInt();
+            int radix = Character.MIN_RADIX + rand.nextInt(Character.MAX_RADIX - Character.MIN_RADIX + 1);
+            assertEquals(Integer.parseUnsignedInt(Integer.toUnsignedString(i, radix), radix), i);
+            if(i >= 0)
+                assertEquals(Integer.toUnsignedString(i, radix), Integer.toString(i, radix));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/Long/LongReducersTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary
+ * @author Tristan Yan
+ * @run testng LongReducersTest
+ */
+
+import java.util.Random;
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+public class LongReducersTest {
+    private final static int LOOP = 1 << 20;
+
+    private final static Random rand = new Random(System.currentTimeMillis());
+
+    @Test
+    public void testMax() {
+        for(int index = 0; index < LOOP; index++){
+            long l1 = rand.nextLong();
+            long l2 = rand.nextLong();
+            long expected = l1 > l2 ? l1 : l2;
+            assertEquals(Long.max(l1, l2), expected);
+        }
+    }
+
+    @Test
+    public void testMin() {
+        for(int index = 0; index < LOOP; index++){
+            long l1 = rand.nextLong();
+            long l2 = rand.nextLong();
+            long expected = l1 < l2 ? l1 : l2;
+            assertEquals(Long.min(l1, l2), expected);
+        }
+    }
+
+    @Test
+    public void testSum() {
+        for(int index = 0; index < LOOP; index++){
+            long l1 = rand.nextLong();
+            long l2 = rand.nextLong();
+            long expected = l1 + l2;
+            assertEquals(Long.sum(l1, l2), expected);
+        }
+    }
+
+    @Test
+    public void testUnsignedWithoutRadix(){
+        for(int index = 0; index < LOOP; index++){
+            long l = rand.nextLong();
+            assertEquals(Long.parseUnsignedLong(Long.toUnsignedString(l)), l);
+            assertEquals(Long.toUnsignedString(l, 10), Long.toUnsignedString(l));
+            if(l >= 0)
+                assertEquals(Long.toUnsignedString(l), Long.toString(l));
+        }
+    }
+
+    @Test
+    public void testUnsignedWithRadix(){
+        for(int index = 0; index < LOOP; index++){
+            long l = rand.nextLong();
+            int radix = Character.MIN_RADIX + rand.nextInt(Character.MAX_RADIX - Character.MIN_RADIX + 1);
+            assertEquals(Long.parseUnsignedLong(Long.toUnsignedString(l, radix), radix), l);
+            if(l >= 0)
+                assertEquals(Long.toUnsignedString(l, radix), Long.toString(l, radix));
+        }
+    }
+
+    @Test
+    public void testCompareUnsigned() {
+        for(int index = 0; index < LOOP; index++){
+            long l1 = rand.nextLong();
+            long l2 = rand.nextLong();
+            assertEquals(Long.compareUnsigned(l1, l2),
+                Long.compare(Long.MAX_VALUE + l1, Long.MAX_VALUE + l2));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/Short/ShortReducersTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary
+ * @(#) ShortReducersTest.java
+ * @author Tristan Yan
+ * @run testng ShortReducersTest
+ */
+
+import java.util.Random;
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+public class ShortReducersTest {
+    private final static int LOOP = Short.MAX_VALUE;
+    private final static Random rand = new Random(System.currentTimeMillis());
+
+    @Test
+    private void testMax() {
+        for (int index = 0; index < LOOP; index++) {
+            short s1 = (short) (rand.nextInt() & 0xffff);
+            short s2 = (short) (rand.nextInt() & 0xffff);
+            short expected = s1 > s2 ? s1 : s2;
+            assertEquals(Short.max(s1, s2), expected);
+        }
+    }
+
+    @Test
+    private void testMin() {
+        for (int index = 0; index < LOOP; index++) {
+            short s1 = (short) (rand.nextInt() & 0xffff);
+            short s2 = (short) (rand.nextInt() & 0xffff);
+            short expected = s1 < s2 ? s1 : s2;
+            assertEquals(Short.min(s1, s2), expected);
+        }
+    }
+
+    @Test
+    private void testSum() {
+        for (int index = 0; index < LOOP; index++) {
+            short s1 = (short) (rand.nextInt() & 0xffff);
+            short s2 = (short) (rand.nextInt() & 0xffff);
+            short expected = (short) (s1 + s2);
+            assertEquals(Short.sum(s1, s2), expected);
+        }
+    }
+
+    @Test
+    private void testUnsigned() {
+        for (int index = 0; index < LOOP; index++) {
+            short s = (short) (rand.nextInt() & 0xffff);
+            assertEquals(Short.toUnsignedInt(s),
+                    (s < 0 ? (int) s + (int) Short.MAX_VALUE - (int) Short.MIN_VALUE + 1 : (int) s));
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/String/JoinTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary test for String.join(CharSequence , CharSequence...) and
+ *          String.join(CharSequence , Iterable<? extends CharSequence>).
+ * @(#) JoinTest.java
+ * @author Tristan Yan
+ * @run testng JoinTest
+ */
+
+import java.util.*;
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+public class JoinTest {
+    private final String[] LANGUAGES = { "ABAP", "ALGOL", "ActionScript",
+        "AppleScript","AspectJ", "Assembly language", "AutoLISP", "AWK", "Bash",
+        "C", "C Shell", "CICS", "COBOL", "Cool", "CSH", "DCL", "Delphi",
+        "Eiffel", "F#", "Formula", "Fortran", "FoxBase", "FoxPro", "Groovy",
+        "Haskell", "J#", "JCL", "JavaScript", "Ksh", "LINC", "Lisp", "Logo",
+        "MASM", "MATLAB", "NASM", "XML", "Objective-C", "Pascal", "Perl",
+        "PL/I", "PostScript", "PowerBuilder", "PowerShell", "Prolog", "Pro*C",
+        "Python", "QBasic", "REBOL", "Ruby", "Scheme", "Sed", "Smalltalk",
+        "SQL", "VBScript" };
+
+
+    private final String[] DELIMETERS = {"`", "~", "!", "@", "#", "$", "%", "^",
+        "&", "*", "(", ")", "-", "_", "+", "=", "\\", "|", ",", ".", "/", ":",
+        ";", "\"", "\"", "\n", "\t", " ", "\t"};
+
+    @Test
+    public void testJoin() {
+        //HashSet sort data with hashCode(), iterator order by hashCode()
+        List<String> lanugageList = Arrays.asList(LANGUAGES);
+        Set<String> lanugageSet = new HashSet<>(lanugageList);
+        Random rnd = new Random();
+        String delimeter = DELIMETERS[rnd.nextInt(DELIMETERS.length)];
+        StringBuilder sb = new StringBuilder();
+        Iterator<String> it = lanugageSet.iterator();
+        int pos = 0;
+        while(it.hasNext()) {
+            sb.append(it.next());
+            if(++pos < lanugageSet.size())
+                sb.append(delimeter);
+        }
+        String result2 = String.join(delimeter, lanugageSet);
+        String result1 = sb.toString();
+        assertEquals(result2, result1);
+
+        Collections.shuffle(lanugageList, new Random(rnd.nextInt()));
+        String[] shuffledArray = new String[lanugageList.size()];
+        lanugageList.toArray(shuffledArray);
+        result1 = String.join(delimeter, shuffledArray);
+        result2 = String.join(delimeter, lanugageList);
+        StringBuilder expectedSB = new StringBuilder();
+        for(int index = 0; index < lanugageList.size() - 1; index++)
+            expectedSB.append(lanugageList.get(index)).append(delimeter);
+        expectedSB.append(lanugageList.get(lanugageList.size() - 1));
+        assertEquals(expectedSB.toString(), result1);
+        assertEquals(result2, result1);
+
+        String single = LANGUAGES[rnd.nextInt(LANGUAGES.length)];
+        assertEquals(String.join(delimeter, new String[]{single}), single);
+        assertEquals(String.join(delimeter, new String[]{single}), single);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/lang/StringBuilder/AddAllTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary test for StringBuilde/StringBuffer.addAll()
+ * @library ../../util
+ * @author Tristan Yan
+ * @run testng AddAllTest
+ */
+
+import java.util.*;
+import java.util.stream.*;
+import static org.testng.Assert.*;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class AddAllTest {
+    private final static int LINE_NUM = 1 << 8;
+
+    private final static int LINE_MIN_CHARACTER_LEN = 2;
+
+    private final static int LINE_MAX_CHARACTER_LEN = 80;
+
+    @Test(dataProvider = "generateData")
+    public void builderAddAll(String[] buff){
+        StringBuilder sb = Arrays.stream(buff).collect(Collectors.toStringBuilder());
+        String str = sb.toString();
+        int start = 0;
+        for(int index = 0; index < buff.length; index++){
+            assert(start + buff[index].length() <= str.length());
+            assertEquals(str.substring(start, start + buff[index].length()), buff[index]);
+            start += buff[index].length();
+        }
+    }
+
+    @Test(dataProvider = "generateData")
+    public void bufferAddAll(String[] buff){
+        StringBuffer sb = Arrays.stream(buff).collect(StringBuffer::new, StringBuffer::append, (s, o) -> s.append(o));
+        String str = sb.toString();
+        int start = 0;
+        for(int index = 0; index < buff.length; index++){
+            assert(start + buff[index].length() <= str.length());
+            assertEquals(str.substring(start, start + buff[index].length()), buff[index]);
+            start += buff[index].length();
+        }
+    }
+
+    @DataProvider
+    public Object[][] generateData(){
+        Object[][] data = new Object[LINE_NUM][];
+        for(int line = 0; line < LINE_NUM; line++) {
+            List<Object> l = new ArrayList<>();
+            String[] buffer = new String[line];
+            for(int row = 0; row < line; row++)
+                buffer[row] = StringUtilities.randomString(LINE_MAX_CHARACTER_LEN,
+                    0);
+            data[line] = new Object[]{buffer};
+        }
+        return data;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/Arrays/ParallelPrefixTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Unit test for Arrays.
+ * @library ../
+ * @(#) ArraysTest.java
+ * @author Tristan Yan
+ * @run testng ParallelPrefixTest
+ */
+
+import java.util.Arrays;
+import java.util.Random;
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+public class ParallelPrefixTest {
+    private final static int ARRAY_SIZE = 1 << 8;
+
+    private final static int MIN_LEN = 1 << 2;
+
+    private final static int MAX_LEN = 1 << 12;
+
+    private final static Random rand = new Random(System.currentTimeMillis());
+
+    private long[] generateLongData(int size) {
+        long[] array = new long[size];
+        for(int i = 0; i < size; i++) {
+            array[i] = rand.nextLong();
+        }
+        return array;
+    }
+
+    private int[] generateIntData(int size) {
+        int[] array = new int[size];
+        for(int i = 0; i < size; i++) {
+            array[i] = rand.nextInt();
+        }
+        return array;
+    }
+
+    private double[] generateDoubleData(int size) {
+        double[] array = new double[size];
+        for(int i = 0; i < size; i++) {
+            array[i] = rand.nextDouble();
+        }
+        return array;
+    }
+
+    private StringBuilder[] generateSBData(int size) {
+        StringBuilder[] array = new StringBuilder[size];
+        for(int i = 0; i < size; i++) {
+            array[i] = new StringBuilder(StringUtilities.randomString(MAX_LEN, MIN_LEN));
+        }
+        return array;
+    }
+
+    @Test
+    public void testParallelPrefixForInt() {
+        int startIndex = rand.nextInt(ARRAY_SIZE);
+        int endIndex = startIndex + rand.nextInt(ARRAY_SIZE + 1 - startIndex);
+
+        int[] intArr1 = generateIntData(ARRAY_SIZE);
+        int[] intArr2 = Arrays.copyOf(intArr1, ARRAY_SIZE);
+        int[] intBackArr = Arrays.copyOf(intArr1, ARRAY_SIZE);
+        Arrays.parallelPrefix(intArr1, LambdaUtilities.addIntBinaryOperator());
+        assertEquals(intArr1.length, intBackArr.length);
+        int totalInt = 0;
+        for(int i = 0; i < ARRAY_SIZE; i++) {
+            totalInt += intBackArr[i];
+            assertEquals(totalInt, intArr1[i]);
+        }
+        Arrays.parallelPrefix(intArr2, startIndex, endIndex, LambdaUtilities.addIntBinaryOperator());
+        totalInt = 0;
+        for(int i = startIndex; i < endIndex; i++) {
+            totalInt += intBackArr[i];
+            assertEquals(totalInt, intArr2[i]);
+        }
+    }
+
+    @Test
+    public void testParallelPrefixForLong() {
+        int startIndex = rand.nextInt(ARRAY_SIZE);
+        int endIndex = startIndex + rand.nextInt(ARRAY_SIZE + 1 - startIndex);
+        long[] longArr1 = generateLongData(ARRAY_SIZE);
+        long[] longArr2 = Arrays.copyOf(longArr1, ARRAY_SIZE);
+        long[] longBackArr = Arrays.copyOf(longArr1, ARRAY_SIZE);
+        Arrays.parallelPrefix(longArr1, LambdaUtilities.addLongBinaryOperator());
+        assertEquals(longArr1.length, longBackArr.length);
+        long totalLong = 0;
+        for(int i = 0; i < ARRAY_SIZE; i++) {
+            totalLong += longBackArr[i];
+            assertEquals(totalLong, longArr1[i]);
+        }
+        Arrays.parallelPrefix(longArr2, startIndex, endIndex, LambdaUtilities.addLongBinaryOperator());
+        totalLong = 0;
+        for(int i = startIndex; i < endIndex; i++) {
+            totalLong += longBackArr[i];
+            assertEquals(totalLong, longArr2[i]);
+        }
+    }
+
+    @Test
+    public void testParallelPrefixForDouble() {
+        //This has potential bug becuase percision could be changed when do
+        //parallel calculation, maybe we should remove parallelPrefix because
+        //it's not so useful
+//                int startIndex = rand.nextInt(ARRAY_SIZE);
+//        int endIndex = startIndex + rand.nextInt(ARRAY_SIZE + 1 - startIndex);
+//        double[] doubleArr1 = generateDoubleData(ARRAY_SIZE);
+//        double[] doubleArr2 = Arrays.copyOf(doubleArr1, ARRAY_SIZE);
+//        double[] doubleBackArr = Arrays.copyOf(doubleArr1, ARRAY_SIZE);
+//        Arrays.parallelPrefix(doubleArr1, LambdaUtilities.addDoubleBinaryOperator());
+//        assertEquals(doubleArr1.length, doubleBackArr.length);
+//        long totalDouble = 0;
+//        for(int i = 0; i < ARRAY_SIZE; i++) {
+//            totalDouble += doubleBackArr[i];
+//            assertEquals(totalDouble, doubleArr1[i]);
+//        }
+//        Arrays.parallelPrefix(doubleArr2, startIndex, endIndex, LambdaUtilities.addDoubleBinaryOperator());
+//        totalDouble = 0;
+//        for(int i = startIndex; i < endIndex; i++) {
+//            totalDouble += doubleBackArr[i];
+//            assertEquals(totalDouble, doubleArr2[i]);
+//        }
+    }
+
+    @Test
+    public void testParallelPrefix() {
+        int startIndex = rand.nextInt(ARRAY_SIZE);
+        int endIndex = startIndex + rand.nextInt(ARRAY_SIZE + 1 - startIndex);
+        StringBuilder[] sbArr1 = generateSBData(ARRAY_SIZE);
+        StringBuilder[] sbArr2 = Arrays.copyOf(sbArr1, ARRAY_SIZE);
+        StringBuilder[] sbBackArr = Arrays.copyOf(sbArr1, ARRAY_SIZE);
+        Arrays.parallelPrefix(sbArr1, LambdaUtilities.appendSBBinaryOperator());
+        assertEquals(sbArr1.length, sbBackArr.length);
+        StringBuilder sbTotal = new StringBuilder();
+        for(int i = 0; i < ARRAY_SIZE; i++) {
+            sbTotal.append(sbBackArr[i]);
+            assertEquals(sbTotal.toString(), sbArr1[i].toString());
+        }
+        Arrays.parallelPrefix(sbArr2, startIndex, endIndex, LambdaUtilities.appendSBBinaryOperator());
+        sbTotal = new StringBuilder();
+        for(int i = startIndex; i < endIndex; i++) {
+            sbTotal.append(sbBackArr[i]);
+            assertEquals(sbTotal.toString(), sbArr2[i].toString());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/Collection/IntRemovePredicateAllTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary sanity tests for Collection.removeAll()/forEach()
+ * @library ../
+ * @(#) IntRemovePredicateAllTest.java
+ * @author Tristan Yan
+ * @run testng IntRemovePredicateAllTest
+ */
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Predicate;
+import static org.testng.Assert.*;
+import org.testng.annotations.Factory;
+import org.testng.annotations.Test;
+
+public class IntRemovePredicateAllTest <T extends Collection<Integer>> {
+    private final static Random rand = new Random(System.currentTimeMillis());
+
+    //1K data is best we can optimize for now.
+    private final static int MAX_SIZE = 1 << 10;
+
+    //At least we should have 4 elements in the list
+    private final static int MIN_SIZE = 1 << 2;
+
+    T t;
+
+    public IntRemovePredicateAllTest(T typeObject1){
+        t = typeObject1;
+    }
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    private static Collection<Integer>
+        generateData(Class<? extends Collection<Integer>> cls,
+            int... initValue) throws InstantiationException,
+            IllegalAccessException, NoSuchMethodException,
+            IllegalArgumentException, InvocationTargetException{
+        Collection<Integer> c;
+        int t1Size = 0;
+        if(initValue.length == 0) {
+            c = cls.newInstance();
+            t1Size= rand.nextInt(MAX_SIZE);
+            if(t1Size < MIN_SIZE) t1Size = MIN_SIZE;
+        } else {
+            Constructor con = cls.getConstructor(int.class);
+            c = (Collection<Integer>)con.newInstance(initValue[0]);
+            t1Size = initValue.length == 2 ? initValue[1] : initValue[0];
+        }
+        for(int i = 0; i < t1Size; i++)
+            c.add(rand.nextInt());
+        return c;
+    }
+
+    @Factory
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public static Object[] create() throws Exception{
+        List<IntRemovePredicateAllTest> result = new ArrayList<>();
+        Class[] defaultConstructorClazz = {
+            (Class<ArrayDeque<Integer>>)(Class<?>)(ArrayDeque.class),
+            (Class<ArrayList<Integer>>)(Class<?>)(ArrayList.class),
+            (Class<ConcurrentLinkedDeque<Integer>>)(Class<?>)(ConcurrentLinkedDeque.class),
+            (Class<ConcurrentLinkedQueue<Integer>>)(Class<?>)(ConcurrentLinkedQueue.class),
+            (Class<ConcurrentSkipListSet<Integer>>)(Class<?>)(ConcurrentSkipListSet.class),
+            (Class<HashSet<Integer>>)(Class<?>)(HashSet.class),
+            (Class<LinkedBlockingDeque<Integer>>)(Class<?>)(LinkedBlockingDeque.class),
+            (Class<LinkedBlockingQueue<Integer>>)(Class<?>)(LinkedBlockingQueue.class),
+            (Class<LinkedHashSet<Integer>>)(Class<?>)(LinkedHashSet.class),
+            (Class<LinkedList<Integer>>)(Class<?>)(LinkedList.class),
+            (Class<LinkedTransferQueue<Integer>>)(Class<?>)(LinkedTransferQueue.class),
+            (Class<PriorityBlockingQueue<Integer>>)(Class<?>)(PriorityBlockingQueue.class),
+            (Class<PriorityQueue<Integer>>)(Class<?>)(PriorityQueue.class),
+            (Class<Stack<Integer>>)(Class<?>)(Stack.class),
+            (Class<TreeSet<Integer>>)(Class<?>)(TreeSet.class),
+            (Class<Vector<Integer>>)(Class<?>)(Vector.class)
+        };
+
+        Class[] capacityConstructorClazz = {
+            (Class<ArrayBlockingQueue<Integer>>)(Class<?>)(ArrayBlockingQueue.class),
+            (Class<ArrayDeque<Integer>>)(Class<?>)(ArrayDeque.class),
+            (Class<ArrayList<Integer>>)(Class<?>)(ArrayList.class),
+            (Class<HashSet<Integer>>)(Class<?>)(HashSet.class),
+            (Class<LinkedBlockingDeque<Integer>>)(Class<?>)(LinkedBlockingDeque.class),
+            (Class<LinkedBlockingQueue<Integer>>)(Class<?>)(LinkedBlockingQueue.class),
+            (Class<LinkedHashSet<Integer>>)(Class<?>)(LinkedHashSet.class),
+            (Class<PriorityBlockingQueue<Integer>>)(Class<?>)(PriorityBlockingQueue.class),
+            (Class<PriorityQueue<Integer>>)(Class<?>)(PriorityQueue.class),
+            (Class<Vector<Integer>>)(Class<?>)(Vector.class)
+        };
+
+        for(int i = 0; i < defaultConstructorClazz.length
+                + capacityConstructorClazz.length; i++) {
+            int initSize1 = rand.nextInt(MAX_SIZE);
+            if(initSize1 < MIN_SIZE) initSize1 = MIN_SIZE;
+            Collection<Integer> c = i < defaultConstructorClazz.length ?
+                generateData(defaultConstructorClazz[i]) :
+                generateData(capacityConstructorClazz[i - defaultConstructorClazz.length],
+                    initSize1);
+            result.add(new IntRemovePredicateAllTest(c));
+        }
+        return result.toArray();
+    }
+
+    @Test
+    public void testRemoveAll() {
+        int limit = rand.nextInt();
+        boolean isUP = rand.nextBoolean();
+        Predicate<Integer> p = LambdaUtilities.randomIntegerPredicate(isUP, limit);
+        t.removeAll(p);
+        assertTrue(verifyMatch(t, limit, !isUP, true));
+    }
+
+    @Test
+    public void testForEach() {
+        final AtomicInteger accumulator = new AtomicInteger(0);
+        t.forEach(t -> accumulator.addAndGet(t));
+
+        Optional<Integer> opi = t.stream().reduce((i1, i2) -> i1 + i2);
+        assertTrue(opi.isPresent());
+        assertEquals(accumulator.get(), opi.get().intValue());
+    }
+
+    private boolean verifyMatch(Collection<Integer> c, int limit, boolean isUP,
+            boolean all) {
+        Iterator<Integer> it = c.iterator();
+        while(it.hasNext()) {
+            int current = it.next();
+            if(isUP) {
+                if(all) {
+                    if(current < limit) return false;
+                } else {
+                    if(current >= limit) return true;
+                }
+            } else {
+                if(all) {
+                    if(current >= limit) return false;
+                } else {
+                    if(current < limit) return true;
+                }
+            }
+        }
+        return all;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/LambdaUtilities.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,759 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @summary This class provide basic support for lambda syntax
+ * @(#) LambdaUtilities.java
+ * @author Tristan Yan
+ */
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.math.BigDecimal;
+import java.nio.file.Path;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.*;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+
+public class LambdaUtilities {
+
+    public static enum CharType {
+        DIGIT, LOWERCASE, UPPERCASE, SPECIAL
+    }
+
+    public static enum StringPredicateType {
+        START_WTIH, NOT_START_WITH, MORE_THAN_LEN, LESS_THAN_LEN
+    }
+
+    public static enum IntOp {
+        ADD, SUBTRACT, MULTIPLY, DIVIDE, MOD
+    }
+
+    public static IntPredicate randomIntPredicate(boolean isUP, int limit) {
+        if (isUP) {
+            return i -> i >= limit;
+        } else {
+            return i -> i < limit;
+        }
+    }
+
+    public static Predicate<Integer> randomIntegerPredicate(boolean isUP, int limit) {
+        if (isUP) {
+            return i -> i >= limit;
+        } else {
+            return i -> i < limit;
+        }
+    }
+
+    public static LongPredicate randomLongPredicate(boolean isUP, long limit) {
+        if (isUP) {
+            return i -> i >= limit;
+        } else {
+            return i -> i < limit;
+        }
+    }
+
+    public static Predicate<Path> startPathPredicate(Path start) {
+        return p -> p.startsWith(start);
+    }
+
+    public static <T> Predicate<T> randomGenericPredicate(boolean isUp, T value, Comparator<T> c) {
+        if (isUp) {
+            return emp -> c.compare(emp, value) >= 0;
+        }else {
+            return emp -> c.compare(emp, value) < 0;
+        }
+    }
+
+    public static Predicate<StringBuilder> randomSBPredicate(StringPredicateType type, String value) {
+        switch (type) {
+            case START_WTIH:
+                return sb -> Character.isDigit(sb.charAt(0));
+            case NOT_START_WITH:
+                return sb -> Character.isLowerCase(sb.charAt(0));
+            case MORE_THAN_LEN:
+                return sb -> Character.isUpperCase(sb.charAt(0));
+            default:
+                return sb -> !Character.isLetterOrDigit(sb.charAt(0));
+        }
+    }
+
+    public static Predicate<? extends CharSequence> randomSBPredicate(CharType startType,
+            boolean first) {
+        switch (startType) {
+            case DIGIT:
+                return sb -> Character.isDigit(sb.charAt(first ? 0 : sb.toString().length() - 1));
+            case LOWERCASE:
+                return sb -> Character.isLowerCase(sb.charAt(first ? 0 : sb.toString().length() - 1));
+            case UPPERCASE:
+                return sb -> Character.isUpperCase(sb.charAt(first ? 0 : sb.toString().length() - 1));
+            default:
+                return sb -> !Character.isLetterOrDigit(sb.charAt(first ? 0 : sb.toString().length() - 1));
+        }
+    }
+
+    public static Predicate<Character> isDigitCharacterPredicate() {
+        return c -> Character.isDigit(c);
+    }
+
+    public static BiConsumer<Stream.Downstream<Integer>, Integer> genIntegerFlatBiConsumer(int selected) {
+        switch (selected) {
+            case 0:
+                //Generate a empty collection
+                return ( s, e ) -> { };
+            case 1:
+                return ( s, e ) -> { s.send(e);
+            }
+            ;
+            case 2:
+                //Generate a triangle has different value
+                return ( s, e ) -> {
+                    for (int i = 0; i < e; i++) {
+                        s.send(e * (e - 1) / 2 + i);
+                    }
+                };
+            case 3:
+                //Generate a triangle has different value
+                return ( s, e ) -> {
+                    for (int i = 0; i < e; i++) {
+                        s.send(e);
+                    }
+                };
+            default:
+                //Generate 64 folded flat map
+                return ( s, e ) -> {
+                    for (int i = 0; i < 1 << 6; i++) {
+                        s.send(e);
+                    }
+                };
+        }
+    }
+
+    public static ObjIntConsumer<IntStream.Downstream> genFlatIntConsumer(int selected) {
+        switch (selected) {
+            case 0:
+                //Generate a empty collection
+                return ( s, e ) -> { };
+            case 1:
+                return ( s, e ) -> { s.send(e);
+            }
+            ;
+            case 2:
+                //Generate a triangle has different value
+                return ( s, e ) -> {
+                    for (int i = 0; i < e; i++) {
+                        s.send(e * (e - 1) / 2 + i);
+                    }
+                };
+            case 3:
+                //Generate a triangle has different value
+                return ( s, e ) -> {
+                    for (int i = 0; i < e; i++) {
+                        s.send(e);
+                    }
+                };
+            default:
+                //Generate 64 folded flat map
+                return ( s, e ) -> {
+                    for (int i = 0; i < 1 << 6; i++) {
+                        s.send(e);
+                    }
+                };
+        }
+    }
+
+    public static BiConsumer<Stream.Downstream<StringBuilder>, StringBuilder> genSBFlatBiConsumer(int selected, int unit) {
+        switch(selected) {
+            case 0:
+                //Generate a empty collection
+                return (s, e) -> { };
+            case 1: return (s, e) -> { s.send(e); };
+            case 2:
+                return (s, e) -> {int step = e.length() / unit + unit -1;
+                                    for (int i = 0; i < e.length(); i += step)
+                                        s.send(new StringBuilder(e.substring(i, i + step >= e.length() ?
+                                                e.length() - 1 : i + step)));};
+            case 3:
+            default:
+                //Generate 64 folded flat map
+                return (s, e) -> {int step = e.length() / unit + unit -1;
+                                    for (int i = 0; i < e.length(); i+=step) s.send(e);};
+        }
+    }
+
+    public static Function<Integer, Integer> posIntegerFunction(boolean isHighest) {
+        if (isHighest) {
+            return i -> Integer.valueOf(new StringBuilder().append(i < 0 ? -i : i).reverse().toString()) % 10;
+        } else {
+            return i -> i % 10 < 0 ? -i % 10 : i % 10;
+        }
+    }
+
+    public static Function<StringBuilder, CharType> sbGenericFunction(boolean isFirst) {
+        if (isFirst)
+            return i -> Character.isAlphabetic(i.charAt(0)) ? (Character.isUpperCase(i.charAt(0)) ? CharType.UPPERCASE : CharType.LOWERCASE) : (Character.isDigit(i.charAt(0)) ? CharType.DIGIT : CharType.SPECIAL);
+            else
+            return i -> Character.isAlphabetic(i.charAt(i.length() - 1)) ? (Character.isUpperCase(i.charAt(i.length() - 1)) ? CharType.UPPERCASE : CharType.LOWERCASE) : (Character.isDigit(i.charAt(i.length() - 1)) ? CharType.DIGIT : CharType.SPECIAL);
+    }
+
+    public static Function<String, Integer> mappingFunction(Map<String, Integer> m, IntOp op, int value) {
+        switch (op) {
+            case ADD:
+                return k -> (value != 0) ? m.get(k) + value : m.get(k);
+            case SUBTRACT:
+                return k -> (value != 0) ? m.get(k) - value : m.get(k);
+            case MULTIPLY:
+                return k -> (value != 0) ? m.get(k) * value : m.get(k);
+            case DIVIDE:
+                return k -> (value != 0) ? m.get(k) / value : m.get(k);
+            default:
+                return k -> (value != 0) ? m.get(k) % value : m.get(k);
+        }
+    }
+
+    public static IntFunction<Integer> posIntFunction(boolean isHighest) {
+        if (isHighest) {
+            return i -> Integer.valueOf(new StringBuilder().append(i < 0 ? -i : i).reverse().toString()) % 10;
+        } else {
+            return i -> i % 10 < 0 ? -i % 10 : i % 10;
+        }
+    }
+
+    public static BiFunction<Integer, Integer, Integer> randBetweenIntegerFunction() {
+        return (t1, t2) -> randBetween(t1, t2);
+    }
+
+    public static int randBetween(int low, int up) {
+        assert (low < up && low >= 0);
+        Random rand = new Random();
+        int i = rand.nextInt(up);
+        while (i < low) {
+            i = rand.nextInt();
+        }
+        return i;
+    }
+
+    public static ToIntFunction<Integer> highestPosValueIntFunction() {
+        return i -> Integer.valueOf(new StringBuilder().append(i < 0 ? -i : i).reverse().toString()) % 10;
+    }
+
+    public static ToIntFunction<Integer> lowestPosValueIntFunction() {
+        return i -> i % 10 < 0 ? -i % 10 : i % 10;
+    }
+
+    public static <T> Consumer<T> reverseConsumer(Set<T> set) {
+        return t -> {
+            set.add(t);
+        };
+    }
+
+    public static Consumer<Integer> addIntegerConsumer(AtomicInteger ai) {
+        return t -> {
+            ai.updateAndGet(t1 -> t1 + t);
+        };
+    }
+
+    public static Consumer<StringBuilder> appendSBConsumer(StringBuilder sb) {
+        return t -> {
+            sb.append(t);
+        };
+    }
+
+    public static IntConsumer addIntConsumer(AtomicInteger ai) {
+        return t -> {
+            ai.updateAndGet(t1 -> t1 + t);
+        };
+    }
+
+    public static IntConsumer addLongConsumer(AtomicLong ai) {
+        return t -> {
+            ai.updateAndGet(t1 -> t1 + t);
+        };
+    }
+
+    public static <T> Consumer<T> copyConsumer(List<T> list) {
+        return t -> {
+            list.add(t);
+        };
+    }
+
+    public static <T> Consumer<T> existsConsumer(Collection<T> in, Collection<T> out) {
+        return t -> {
+            if (in.contains(t)) {
+                out.add(t);
+            }
+        };
+    }
+
+    public static Supplier<StringBuilder> sbSupplier(StringBuilder value) {
+        return () -> value;
+    }
+
+    public static Supplier<Integer> integerSupplier(int value) {
+        return () -> value;
+    }
+
+    public static <T> Supplier<T> genericSuppiler(T value) {
+        return () -> value;
+    }
+
+    public static IntSupplier intSupplier(int value) {
+        return () -> value;
+    }
+
+    public static Supplier<Long> longSupplier(long value) {
+        return () -> value;
+    }
+
+    public static Supplier<AtomicInteger> atomicIntegerSupplier(int value) {
+        return () -> new AtomicInteger(0);
+    }
+
+    public static <T> Supplier<AtomicReference<T>> atomicGenericSupplier(T value) {
+        return () -> new AtomicReference<>(value);
+    }
+
+    public static Supplier<AtomicReference<StringBuilder>> atomicSBSupplier(StringBuilder value) {
+        return () -> new AtomicReference<>(value);
+    }
+
+    public static UnaryOperator<Integer> opIntegerUnaryOperator(IntOp op, int value) {
+        switch (op) {
+            case ADD:
+                return t -> t + value;
+            case SUBTRACT:
+                return t -> t - value;
+            case MULTIPLY:
+                return t -> t * value;
+            case DIVIDE:
+                return t -> t / value;
+            default:
+                return t -> t % value;
+        }
+    }
+
+    public static IntUnaryOperator opIntUnaryOperator(IntOp op, int value) {
+        if(value == 0)
+            return t -> t;
+        switch (op) {
+            case ADD:
+                return t -> t + value;
+            case SUBTRACT:
+                return t -> t - value;
+            case MULTIPLY:
+                return t -> t * value;
+            case DIVIDE:
+                return t -> t / value;
+            default:
+                return t -> t % value;
+        }
+    }
+
+    public static Function<Integer, Integer> opIntegerFunction(IntOp op, int value) {
+        if(value == 0)
+            return t -> t;
+        switch (op) {
+            case ADD:
+                return t -> Integer.valueOf(t + value);
+            case SUBTRACT:
+                return t -> Integer.valueOf(t - value);
+            case MULTIPLY:
+                return t -> Integer.valueOf(t * value);
+            case DIVIDE:
+                return t -> Integer.valueOf(t / value);
+            default:
+                return t -> Integer.valueOf(t % value);
+        }
+    }
+
+    public static ToIntFunction<Integer> opToIntFunction(IntOp op, int value) {
+        if(value == 0)
+            return t -> t.intValue();
+        switch (op) {
+            case ADD:
+                return t -> t.intValue() + value;
+            case SUBTRACT:
+                return t -> t.intValue() - value;
+            case MULTIPLY:
+                return t -> t.intValue() * value;
+            case DIVIDE:
+                return t -> t.intValue() / value;
+            default:
+                return t -> t.intValue() % value;
+        }
+    }
+
+    public static IntFunction<Integer> opIntFunction(IntOp op, int value) {
+        if(value == 0)
+            return t -> t;
+        switch (op) {
+            case ADD:
+                return t -> t + value;
+            case SUBTRACT:
+                return t -> t - value;
+            case MULTIPLY:
+                return t -> t * value;
+            case DIVIDE:
+                return t -> t / value;
+            default:
+                return t -> t % value;
+        }
+    }
+
+    public static IntUnaryOperator addIntUnaryOperator(int value) {
+        return t -> t + value;
+    }
+
+    public static IntUnaryOperator subIntUnaryOperator(int value) {
+        return t -> t - value;
+    }
+
+    public static IntUnaryOperator mulIntUnaryOperator(int value) {
+        return t -> t * value;
+    }
+
+    public static IntUnaryOperator divIntUnaryOperator(int value) {
+        return t -> t / value;
+    }
+
+    public static IntBinaryOperator minIntBinaryOperator() {
+        return (t1, t2) -> t1< t2 ? t1 : t2;
+    }
+
+    public static BinaryOperator<Integer> minIntegerBinaryOperator(Comparator<Integer> c) {
+        return (t1, t2) -> c.compare(t1, t2) < 0 ? t1 : t2;
+    }
+
+    public static <T>BinaryOperator<T> minGenericBinaryOperator(Comparator<T> c) {
+        return (t1, t2) -> c.compare(t1, t2) < 0 ? t1 : t2;
+    }
+
+    public static BinaryOperator<StringBuilder> minSBBinaryOperator(Comparator<StringBuilder>  c) {
+        return ( t1, t2 ) -> c.compare(t1, t2) < 0 ? t1 : t2;
+    }
+
+    public static IntBinaryOperator maxIntBinaryOperator() {
+        return ( t1, t2 ) -> (t1< t2) ? t2: t1;
+    }
+
+    public static BinaryOperator<Integer> maxIntegerBinaryOperator(Comparator<Integer>  c) {
+        return (t1, t2) -> c.compare(t1, t2) < 0 ? t2 : t1;
+    }
+
+    public static <T> BinaryOperator<T> maxGenericBinaryOperator(Comparator<T>  c) {
+        return (t1, t2) -> c.compare(t1, t2) < 0 ? t2 : t1;
+    }
+
+    public static IntBinaryOperator maxIntBinaryOperator(Comparator<Integer>  c) {
+        return ( t1, t2 ) -> c.compare(t1, t2) < 0 ? t2 : t1;
+    }
+
+    public static BinaryOperator<StringBuilder> maxSBBinaryOperator(Comparator<StringBuilder>  c) {
+        return ( t1, t2 ) -> c.compare(t1, t2) < 0 ? t2 : t1;
+    }
+
+    public static BinaryOperator<Integer> addIntegerBinaryOperator() {
+        return ( t1 , t2 ) -> t1 + t2;
+    }
+
+    public static IntBinaryOperator addIntBinaryOperator() {
+        return ( t1 , t2 ) -> t1 + t2;
+    }
+
+    public static BinaryOperator<BigDecimal> addBigDecimalBinaryOperator() {
+        return ( t1 , t2 ) -> t1.add(t2);
+    }
+
+    public static DoubleBinaryOperator addDoubleBinaryOperator() {
+        return ( t1 , t2 ) -> t1 + t2;
+    }
+
+    public static BinaryOperator<StringBuilder> appendSBBinaryOperator() {
+        return (t1 , t2) -> new StringBuilder().append(t1).append(t2);
+    }
+
+    public static BinaryOperator<Integer> subIntegerBinaryOperator() {
+        return (t1, t2) -> t1 - t2;
+    }
+
+    public static IntBinaryOperator subIntBinaryOperator() {
+        return (t1, t2) -> t1 - t2;
+    }
+
+    public static BinaryOperator<StringBuilder> deleteSBBinaryOperator() {
+        return (t1, t2) -> {if (t1.length() >= t2.length()) {
+                                int i1 = t1.indexOf(t2.toString());
+                                int i2 = i1 + t2.length();
+                                return new StringBuilder(t1).delete(i1, i2);
+                            }else {
+                                int i1 = t2.indexOf(t1.toString());
+                                int i2 = i1 + t1.length();
+                                return new StringBuilder(t2).delete(i1, i2);
+                            }
+        };
+
+    }
+
+    public static IntBinaryOperator mulIntBinaryOperator() {
+        return (t1, t2) -> t1 * t2;
+    }
+
+    public static IntBinaryOperator divIntBinaryOperator() {
+        return (t1, t2) -> t1 / t2;
+    }
+
+    public static LongUnaryOperator addLongUnaryOperator(long value) {
+        return t -> t + value;
+    }
+
+    public static UnaryOperator<StringBuilder> appendSBUnaryOperator(StringBuilder value) {
+        return t -> t.append(value);
+    }
+
+    public static LongUnaryOperator subLongUnaryOperator(long value) {
+        return t -> t - value;
+    }
+
+    public static LongUnaryOperator mulLongUnaryOperator(long value) {
+        return t -> t * value;
+    }
+
+    public static LongUnaryOperator divLongUnaryOperator(long value) {
+        return t -> t / value;
+    }
+
+    public static LongBinaryOperator addLongBinaryOperator() {
+        return (t1, t2) -> t1 + t2;
+    }
+
+    public static LongBinaryOperator subLongBinaryOperator() {
+        return (t1, t2) -> t1 - t2;
+    }
+
+    public static LongBinaryOperator mulLongBinaryOperator() {
+        return (t1, t2) -> t1 * t2;
+    }
+
+    public static LongBinaryOperator divLongBinaryOperator() {
+        return (t1, t2) -> t1 / t2;
+    }
+
+    public static BiConsumer<AtomicInteger, Integer> addIntegerBiConsumer() {
+        return (t1 , t2 ) -> {  t1.addAndGet(t2); };
+    }
+
+    public static BiConsumer<AtomicInteger, AtomicInteger> addAtomicIntegerBiConsumer() {
+        return (t1 , t2) -> {  t1.addAndGet(t2.get()); };
+    }
+
+    public static BiConsumer<AtomicReference<StringBuilder>, StringBuilder> appendSBBiConsumer() {
+        return (t1, t2) -> {t1.updateAndGet(appendSBUnaryOperator(t2));};
+    }
+
+    public static BiConsumer<AtomicReference<StringBuilder>, AtomicReference<StringBuilder>> appendAtomicSBBiConsumer() {
+        return (t1, t2) -> {t1.updateAndGet(appendSBUnaryOperator(t2.get()));};
+    }
+
+    public static BiConsumer<AtomicInteger, Integer> maxIntegerBiConsumer(Comparator<Integer> c) {
+        return (t1 , t2 ) -> {  t1.getAndUpdate(t -> max(t, t2, c)); };
+    }
+
+    public static <T> BiConsumer<AtomicReference<T>, T> maxGenericBiConsumer(Comparator<T> c) {
+        return (t1 , t2 ) -> {  t1.getAndUpdate(t -> max(t, t2, c)); };
+    }
+
+    public static BiConsumer<AtomicInteger, AtomicInteger> maxAtomicIntegerBiConsumer(Comparator<Integer> c) {
+        return (t1 , t2) -> {  t1.getAndUpdate(t -> max(t, t2.get(), c)); };
+    }
+
+    public static <T> BiConsumer<AtomicReference<T>, AtomicReference<T>> maxAtomicGenericBiConsumer(Comparator<T> c) {
+        return (t1 , t2) -> {  t1.getAndUpdate(t -> max(t, t2.get(), c)); };
+    }
+
+    public static BiConsumer<AtomicInteger, Integer> minIntegerBiConsumer(Comparator<Integer> c) {
+        return (t1 , t2) -> {  t1.getAndUpdate(t -> min(t, t2, c)); };
+    }
+
+    public static <T> BiConsumer<AtomicReference<T>, T> minGenericBiConsumer(Comparator<T> c) {
+        return (t1 , t2) -> {  t1.getAndUpdate(t -> min(t, t2, c)); };
+    }
+
+    public static BiConsumer<AtomicInteger, AtomicInteger> minAtomicIntegerBiConsumer(Comparator<Integer> c) {
+        return (t1, t2) -> {  t1.getAndUpdate(t -> min(t, t2.get(), c)); };
+    }
+
+    public static <T> BiConsumer<AtomicReference<T>, AtomicReference<T>> minAtomicGenericBiConsumer(Comparator<T> c) {
+        return (t1, t2) -> {  t1.getAndUpdate(t -> min(t, t2.get(), c)); };
+    }
+
+    public static BiFunction<Integer, Integer, Integer> maxIntegerFunction(Comparator<Integer> c) {
+        return (t1, t2) -> max(t1, t2, c);
+    }
+
+    public static BiFunction<BigDecimal, Integer, BigDecimal> deviationSequareFunction(double avg) {
+        return (bd, t) -> bd.add(new BigDecimal(avg - t).pow(2));
+    }
+
+    public static <T> BiFunction<T, T, T> maxGenericFunction(Comparator<T> c) {
+        return (t1, t2) -> max(t1, t2, c);
+    }
+
+    public static BiFunction<StringBuilder, StringBuilder, StringBuilder> maxStringBuilderFunction(Comparator<StringBuilder> c) {
+        return (t1, t2) -> max(t1, t2, c);
+    }
+
+    public static BiFunction<Integer, Integer, Integer> minIntegerFunction(Comparator<Integer> c) {
+        return (t1, t2) -> min(t1, t2, c);
+    }
+
+    public static <T> BiFunction<T, T, T> minGenericFunction(Comparator<T> c) {
+        return (t1, t2) -> min(t1, t2, c);
+    }
+
+    public static BiFunction<StringBuilder, StringBuilder, StringBuilder> minStringBuilderFunction(Comparator<StringBuilder> c) {
+        return (t1, t2) -> min(t1, t2, c);
+    }
+
+    public static BiFunction<String, Integer, Integer> opBiFunction(IntOp op, int value) {
+        switch (op) {
+            case ADD:
+                return (k, v) -> (value != 0) ? v + value : v;
+            case SUBTRACT:
+                return (k, v) -> (value != 0) ? v - value : v;
+            case MULTIPLY:
+                return (k, v) -> (value != 0) ? v * value : v;
+            case DIVIDE:
+                return (k, v) -> (value != 0) ? v / value : v;
+            default:
+                return (k, v) -> (value != 0) ? v % value : v;
+        }
+    }
+
+
+    public static BiFunction<Integer, Integer, Integer> opBiFunction(IntOp op) {
+        switch (op) {
+            case ADD:
+                return (oldv, v) -> (v != 0) ? oldv + v : oldv;
+            case SUBTRACT:
+                return (oldv, v) -> (v != 0) ? oldv - v : oldv;
+            case MULTIPLY:
+                return (oldv, v) -> (v != 0) ? oldv * v : oldv;
+            case DIVIDE:
+                return (oldv, v) -> (v != 0) ? oldv / v : oldv;
+            default:
+                return (oldv, v) -> (v != 0) ? oldv % v : oldv;
+        }
+    }
+
+    private static Integer min(Integer i1, Integer i2, Comparator<Integer> c) {
+        return c.compare(i1, i2) < 0 ? i1 : i2;
+    }
+
+    private static <T> T min(T i1, T i2, Comparator<T> c) {
+        return c.compare(i1, i2) < 0 ? i1 : i2;
+    }
+
+    private static StringBuilder min(StringBuilder sb1, StringBuilder sb2, Comparator<StringBuilder> c) {
+        return c.compare(sb1, sb2) < 0 ? sb1 : sb2;
+    }
+
+    private static Integer max(Integer i1, Integer i2, Comparator<Integer> c) {
+        return c.compare(i1, i2) < 0 ? i2 : i1;
+    }
+
+    private static <T> T max(T i1, T i2, Comparator<T> c) {
+        return c.compare(i1, i2) < 0 ? i2 : i1;
+    }
+
+    private static StringBuilder max(StringBuilder sb1, StringBuilder sb2, Comparator<StringBuilder> c) {
+        return c.compare(sb1, sb2) < 0 ? sb2 : sb1;
+    }
+    /*
+     * Construct a Collection C object based on a C object, using generic type
+     * instead of Class type can help preventing type error in compilation
+     */
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public static <E, C extends Collection<E>>  C create(C c, int... initSize)
+            throws InstantiationException, IllegalAccessException,
+            NoSuchMethodException, IllegalArgumentException,
+            InvocationTargetException {
+        return create((Class<C>) c.getClass(), initSize);
+    }
+
+    /*
+     * Construct a Collection C object based on a C's type, using generic type
+     * instead of Class type can help preventing type error in compilation
+     */
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public static <E, T extends Collection<E>>  T create(
+            Class<? extends Collection<E>> cls, int... initSize)
+            throws InstantiationException, IllegalAccessException,
+            NoSuchMethodException, IllegalArgumentException,
+            InvocationTargetException {
+        assert (initSize.length <= 1);
+        Collection<E> c;
+        if (initSize.length == 0) {
+            c = cls.newInstance();
+        } else {
+            Constructor con = cls.getConstructor(int.class);
+            c = (Collection<E>) con.newInstance(initSize[0]);
+        }
+        return (T) c;
+    }
+
+    /*
+     * Construct a T object based on T's type, using generic type instead of
+     * Class type can help preventing type error in compilation
+     */
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public static <K, V, M extends Map<K, V>>  M createMap(M m, int... initSize)
+            throws InstantiationException, IllegalAccessException,
+            NoSuchMethodException, IllegalArgumentException,
+            InvocationTargetException {
+        return createMap((Class<M>) m.getClass(), initSize);
+    }
+
+    /*
+     * Construct a Map M object based on M's type, using generic type instead of
+     * Class type can help preventing type error in compilation
+     */
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public static <K, V, M extends Map<K, V>>  M createMap(Class<? extends Map<K, V>> cls,
+            int... initSize) throws InstantiationException,
+            IllegalAccessException, NoSuchMethodException,
+            IllegalArgumentException, InvocationTargetException {
+        assert (initSize.length <= 1);
+        Map<K, V> map;
+        if (initSize.length == 0) {
+            map = cls.newInstance();
+        } else {
+            Constructor con = cls.getConstructor(int.class);
+            map = (Map<K, V>) con.newInstance(initSize[0]);
+        }
+        return (M) map;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/List/ExtensionsTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Basic tests for List's extension methods
+ * @library ../
+ * @(#) ListTest.java
+ * @author Tristan Yan
+ * @run testng ExtensionsTest
+ */
+
+import java.util.*;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.stream.Stream;
+import static org.testng.Assert.*;
+import org.testng.annotations.*;
+
+public class ExtensionsTest<T extends List<Integer>> {
+    protected Class<T> typeObject;
+
+    protected boolean hasIni;
+
+    protected int initSize;
+
+    protected final static int START = -1 << 6;
+
+    protected final static int END = 1 << 6;
+
+    protected final static Random rand = new Random(System.currentTimeMillis());
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    protected static Class[] defaultConstructorClazz = {
+        (Class<ArrayList<Integer>>)(Class<?>)(ArrayList.class),
+        (Class<CopyOnWriteArrayList<Integer>>)(Class<?>)(CopyOnWriteArrayList.class),
+        (Class<LinkedList<Integer>>)(Class<?>)(LinkedList.class),
+        (Class<Stack<Integer>>)(Class<?>)(Stack.class),
+        (Class<Vector<Integer>>)(Class<?>)(Vector.class)
+    };
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    protected static Class[] capacityConstructorClazz = {
+        (Class<ArrayList<Integer>>)(Class<?>)(ArrayList.class),
+        (Class<Vector<Integer>>)(Class<?>)(Vector.class)
+    };
+
+    public ExtensionsTest(Class<T> clazz, int... initSizes){
+        this.typeObject = clazz;
+        assert(initSizes.length <= 1);
+        if(initSizes.length == 1) {
+            hasIni = true;
+            this.initSize = initSizes[0];
+        }
+    }
+
+    protected List<Integer> generateList(int start, int end, int size)
+            throws Exception{
+        List<Integer> list =  hasIni ?
+            (List<Integer>)LambdaUtilities.create(typeObject, initSize) :
+            (List<Integer>)LambdaUtilities.create(typeObject);
+        for(int i = 0; i < size; i++) {
+            int element = start + rand.nextInt(end - start);
+            list.add(element);
+        }
+        return list;
+    }
+
+    protected List<Integer> generateList(int start, int end) throws Exception{
+        return generateList(start, end, end - start);
+    }
+
+    @Factory
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public static Object[] create(){
+        List<ExtensionsTest> result = new ArrayList<>();
+        Stream<Class> stream1 = Arrays.stream(defaultConstructorClazz);
+        Stream<Class> stream2 = Arrays.stream(capacityConstructorClazz);
+        stream1.forEach(clazz -> result.add(new ExtensionsTest(clazz)));
+        stream2.forEach(clazz -> result.add(new ExtensionsTest(clazz,
+                END - START + rand.nextInt(END - START))));
+        return result.toArray();
+    }
+
+    @Test
+    public void testReplaceAll() throws Exception {
+        List<Integer> list = generateList(START, END);
+        List<Integer> listCloned =  hasIni ?
+            (List<Integer>)LambdaUtilities.create(typeObject, initSize) :
+            (List<Integer>)LambdaUtilities.create(typeObject);
+        listCloned.addAll(list);
+        EnumSet<LambdaUtilities.IntOp> set = EnumSet.allOf(LambdaUtilities.IntOp.class);
+        LambdaUtilities.IntOp[] ops = new LambdaUtilities.IntOp[set.size()];
+        set.toArray(ops);
+        LambdaUtilities.IntOp op = ops[rand.nextInt(ops.length)];
+        int value = START + rand.nextInt(END - START);
+        if( op == LambdaUtilities.IntOp.DIVIDE || op == LambdaUtilities.IntOp.MOD)
+            while(value == 0)
+                value = START + rand.nextInt(END - START);
+        list.replaceAll(LambdaUtilities.opIntegerUnaryOperator(op, value));
+        checkReplace(listCloned, list, op, value);
+    }
+
+    @Test
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public void testSort() throws Exception{
+        Comparator[] cs = { Comparators.<Integer>naturalOrder(),
+            Comparators.<Integer>reverseOrder(),
+            Comparators.comparing(LambdaUtilities.highestPosValueIntFunction() ),
+            Comparators.comparing(LambdaUtilities.lowestPosValueIntFunction() ),
+        };
+
+        Iterator<Comparator> csit = Arrays.stream(cs).iterator();
+        while(csit.hasNext())
+            testComparator((Comparator<Integer>)csit.next());
+    }
+
+    @Test
+    public void testRemoveAll() throws Exception {
+        List<Integer> list = generateList(START, END);
+        int limit = rand.nextInt(2 * (END - START)) + 2 * START;
+        boolean isUP = rand.nextBoolean();
+        list.removeAll(LambdaUtilities.randomIntegerPredicate(isUP, limit));
+        assertTrue(verifyMatch(list, limit, !isUP, true));
+    }
+
+    @Test
+    public void testForEach() throws Exception {
+        List<Integer> list = generateList(START, END);
+        List<Integer> listCloned =  hasIni ?
+            (List<Integer>)LambdaUtilities.create(typeObject, initSize) :
+            (List<Integer>)LambdaUtilities.create(typeObject);
+        list.forEach(LambdaUtilities.copyConsumer(listCloned));
+        assertEquals(list, listCloned);
+    }
+    private void checkReplace(List<Integer> orig, List<Integer> replaced,
+            LambdaUtilities.IntOp op, int value) {
+        assertEquals(orig.size(), replaced.size());
+        for(int index = 0; index < orig.size(); index++)
+            switch(op) {
+                case ADD:
+                    assertTrue(orig.get(index) + value == replaced.get(index));
+                    break;
+                case SUBTRACT:
+                    assertTrue(orig.get(index) - value == replaced.get(index));
+                    break;
+                case MULTIPLY:
+                    assertTrue(orig.get(index) * value == replaced.get(index));
+                    break;
+                case DIVIDE:
+                    assertTrue(orig.get(index) / value == replaced.get(index));
+                    break;
+                default:
+                    assertTrue(orig.get(index) % value == replaced.get(index));
+                    break;
+            }
+    }
+
+    private void testComparator(Comparator<Integer> c) throws Exception {
+        List<Integer> list = generateList(START, END);
+        List<Integer> listCloned =  hasIni ?
+            (List<Integer>)LambdaUtilities.create(typeObject, initSize) :
+            (List<Integer>)LambdaUtilities.create(typeObject);
+        listCloned.addAll(list);
+        list.sort(c);
+        for(int i = 0; i < list.size() - 1; i++)
+            assertTrue(c.compare(list.get(i), list.get(i+1)) <= 0);
+        //assertEquals(list, listCloned);
+    }
+
+    private boolean verifyMatch(Collection<Integer> c, int limit, boolean isUP,
+            boolean all) {
+        Iterator<Integer> it = c.iterator();
+        while(it.hasNext()) {
+            int current = it.next();
+            if(isUP) {
+                if(all) {
+                    if(current < limit) return false;
+                } else {
+                    if(current >= limit) return true;
+                }
+            } else {
+                if(all) {
+                    if(current >= limit) return false;
+                } else {
+                    if(current < limit) return true;
+                }
+            }
+        }
+        return all;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/Map/LambdaTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary sanity test forEach on Map<String,Integer>
+ * @library ../
+ * @(#)LambdaTest.java
+ * @author Yong Lu/Tristan Yan
+ * @run testng LambdaTest
+ */
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.stream.Stream;
+import static org.testng.Assert.*;
+import org.testng.ITest;
+import org.testng.annotations.Factory;
+import org.testng.annotations.Test;
+
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class LambdaTest<T extends Map<String, Integer>> implements ITest  {
+    private final static Random rand = new Random(System.currentTimeMillis());
+    private Class<T> typeObject;
+    private boolean hasIni;
+    private int initSize;
+
+    private final static int START = -1 << 6;
+    private final static int END = 1 << 6;
+
+    private static Class[] defaultConstructorClazz = {
+        (Class<ConcurrentHashMap<String, Integer>>) (Class<?>) (ConcurrentHashMap.class),
+        (Class<ConcurrentSkipListMap<String, Integer>>) (Class<?>) (ConcurrentSkipListMap.class),
+        (Class<HashMap<String, Integer>>) (Class<?>) (HashMap.class),
+        (Class<Hashtable<String, Integer>>) (Class<?>) (Hashtable.class),
+        (Class<LinkedHashMap<String, Integer>>) (Class<?>) (LinkedHashMap.class),
+        (Class<IdentityHashMap<String, Integer>>) (Class<?>) (IdentityHashMap.class),
+        (Class<WeakHashMap<String, Integer>>) (Class<?>) (WeakHashMap.class)
+    };
+
+    public LambdaTest(Class<T> clazz, int... initSizes) {
+        this.typeObject = clazz;
+        assert (initSizes.length <= 1);
+        if (initSizes.length == 1) {
+            hasIni = true;
+            this.initSize = initSizes[0];
+        }
+    }
+
+    protected Map<String, Integer> generateData(int start, int end, int size) throws Exception {
+        Map<String, Integer> m = LambdaUtilities.createMap(typeObject);
+        for (int i = 0; i < size; i++) {
+            int element = start + rand.nextInt(end - start);
+            if (element != Integer.SIZE) {
+                m.put(String.valueOf(element), new Integer(element));
+            }
+        }
+        return m;
+    }
+
+    protected Map<String, Integer> generateData(int start, int end) throws Exception {
+        return generateData(start, end, end - start);
+    }
+
+    @Factory
+    public static Object[] create(){
+        List<LambdaTest> result = new ArrayList<>();
+        Stream<Class> stream = Arrays.stream(defaultConstructorClazz);
+        stream.forEach(clazz -> result.add(new LambdaTest(clazz)));
+        return result.toArray();
+    }
+
+    @Test
+    public void testForEach() throws Exception{
+        Map<String, Integer> m1 = generateData(START, END);
+        m1.forEach((x,y) -> assertTrue(m1.get(x).equals(y)));
+
+        Map<String, Integer> m2 = LambdaUtilities.createMap(typeObject);
+        m1.forEach((x,y) -> m2.put(x, y));
+        m2.forEach((x,y) -> assertTrue(m1.get(x).equals(y)));
+
+        m1.forEach((x,y) -> {
+                m1.put(x, Integer.SIZE);
+                assertFalse(m1.containsValue(y));
+        });
+    }
+
+    @Test
+    public void testReplaceAll() throws Exception{
+        //ConcurrentSkipListMap doesn't replaceAll
+        if(typeObject.getName().endsWith("ConcurrentSkipListMap"))
+            return;
+        Map<String, Integer> m = generateData(START, END);
+        Map<String, Integer> mCloned = LambdaUtilities.createMap(typeObject);
+        mCloned.putAll(m);
+        EnumSet<LambdaUtilities.IntOp> set = EnumSet.allOf(LambdaUtilities.IntOp.class);
+        LambdaUtilities.IntOp[] ops = new LambdaUtilities.IntOp[set.size()];
+        set.toArray(ops);
+        LambdaUtilities.IntOp op = ops[rand.nextInt(ops.length)];
+        int value = START + rand.nextInt(END - START);
+        while((value = START + rand.nextInt(END - START)) == 0);
+        m.replaceAll(LambdaUtilities.opBiFunction(op, value));
+        checkReplace(mCloned, m, op, value);
+    }
+
+    @Test
+    public void testCompute() throws Exception{
+        Map<String, Integer> m = generateData(START, END);
+        Map<String, Integer> mCloned = LambdaUtilities.createMap(typeObject);
+        mCloned.putAll(m);
+        final int value = START + rand.nextInt(END - START);
+        EnumSet<LambdaUtilities.IntOp> set = EnumSet.allOf(LambdaUtilities.IntOp.class);
+        LambdaUtilities.IntOp[] ops = new LambdaUtilities.IntOp[set.size()];
+        set.toArray(ops);
+        LambdaUtilities.IntOp op = ops[rand.nextInt(ops.length)];
+        mCloned.keySet().forEach(t -> m.compute(t, LambdaUtilities.opBiFunction(op, value)));
+        checkReplace(mCloned, m, op, value);
+    }
+
+    @Test
+    public void testMerge() throws Exception{
+        Map<String, Integer> m = generateData(START, END);
+        Map<String, Integer> mCloned = LambdaUtilities.createMap(typeObject);
+        mCloned.putAll(m);
+        final int value = START + rand.nextInt(END - START);
+        EnumSet<LambdaUtilities.IntOp> set = EnumSet.allOf(LambdaUtilities.IntOp.class);
+        LambdaUtilities.IntOp[] ops = new LambdaUtilities.IntOp[set.size()];
+        set.toArray(ops);
+        LambdaUtilities.IntOp op = ops[rand.nextInt(ops.length)];
+        mCloned.keySet().forEach(t -> m.merge(t, value, LambdaUtilities.opBiFunction(op)));
+        checkReplace(mCloned, m, op, value);
+    }
+
+    @Test
+    public void testReplace() throws Exception{
+        Map<String, Integer> m = generateData(START, END);
+        Map<String, Integer> mCloned = LambdaUtilities.createMap(typeObject);
+        mCloned.putAll(m);
+        final int value = START + rand.nextInt(END - START);
+        EnumSet<LambdaUtilities.IntOp> set = EnumSet.allOf(LambdaUtilities.IntOp.class);
+        LambdaUtilities.IntOp[] ops = new LambdaUtilities.IntOp[set.size()];
+        set.toArray(ops);
+        LambdaUtilities.IntOp op = ops[rand.nextInt(ops.length)];
+        mCloned.keySet().forEach(t -> m.replace(t, mCloned.get(t), LambdaUtilities.opBiFunction(op).apply(mCloned.get(t), value)));
+        checkReplace(mCloned, m, op, value);
+    }
+
+    private void checkReplace(Map<String, Integer> orig, Map<String, Integer> replaced,
+            LambdaUtilities.IntOp op, int value) {
+        assertEquals(orig.size(), replaced.size());
+        Iterator<String> it = orig.keySet().iterator();
+        while(it.hasNext()) {
+            String k = it.next();
+            if(value == 0){
+                assertEquals(orig.get(k), replaced.get(k));
+                continue;
+            }
+            switch(op) {
+                case ADD:
+                    assertTrue(orig.get(k) + value == replaced.get(k));
+                    break;
+                case SUBTRACT:
+                    assertTrue(orig.get(k) - value == replaced.get(k));
+                    break;
+                case MULTIPLY:
+                    assertTrue(orig.get(k) * value == replaced.get(k));
+                    break;
+                case DIVIDE:
+                    assertTrue(orig.get(k) / value == replaced.get(k));
+                    break;
+                default:
+                    assertTrue(orig.get(k) % value == replaced.get(k));
+                    break;
+            }
+        }
+    }
+
+    @Test
+    public void testRemove() throws Exception {
+        Map<String, Integer> m = generateData(START, END);
+        Map<String, Integer> mCloned = LambdaUtilities.createMap(typeObject);
+        mCloned.putAll(m);
+        mCloned.keySet().forEach(t -> m.remove(t));
+        assertTrue(m.isEmpty());
+    }
+
+    @Test
+    public void testComputeIfAbsent() throws Exception {
+        Map<String, Integer> m = generateData(START, END);
+        Map<String, Integer> mCloned = LambdaUtilities.createMap(typeObject);
+        final int value = START + rand.nextInt(END - START);
+        EnumSet<LambdaUtilities.IntOp> set = EnumSet.allOf(LambdaUtilities.IntOp.class);
+        LambdaUtilities.IntOp[] ops = new LambdaUtilities.IntOp[set.size()];
+        set.toArray(ops);
+        LambdaUtilities.IntOp op = ops[rand.nextInt(ops.length)];
+        m.keySet().forEach(t -> mCloned.computeIfAbsent(t, LambdaUtilities.mappingFunction(m, op, value)));
+        checkReplace(m, mCloned, op, value);
+    }
+
+    @Override
+    public String getTestName() {
+        return typeObject.getName() + "<String,Integer>";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/StringJoiner/BasicTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Sanity Test for StringJoiner
+ * @(#) BasicTest.java
+ * @library ../
+ * @author Tristan Yan
+ * @run testng BasicTest
+ */
+
+import java.util.*;
+import java.util.stream.Collectors;
+import static org.testng.Assert.*;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class BasicTest {
+    protected final static int STRING_ARR_SIIE = 1 << 8;
+
+    protected final static int STRING_LEN = 1 << 10;
+
+    protected final static int TIMES = 1 << 4;
+
+    protected final static Random rnd = new Random(System.currentTimeMillis());
+
+    protected String[] randomStringArray(){
+       String[] arr = new String[STRING_ARR_SIIE];
+       for(int index = 0; index < STRING_ARR_SIIE; index++)
+           arr[index] = StringUtilities.randomAlphabetic(rnd.nextInt(STRING_LEN));
+       return arr;
+    }
+
+    @DataProvider(name = "Connector-Provider")
+    public Object[][] notAlphanumeric(){
+        Object[][] data = new Object[TIMES][3];
+        for(int i = 0; i < TIMES; i++) {
+            List<String> list = new ArrayList<>();
+            for(char c=32; c < 127; c++) {
+                if(!Character.isAlphabetic(c) && !Character.isDigit(c))
+                    list.add(String.valueOf(c));
+            }
+            Collections.shuffle(list);
+            int infixPos = rnd.nextInt(list.size()/2);
+            if(infixPos < 1) infixPos = 1;
+            int prefixPos = infixPos + rnd.nextInt(list.size() - infixPos);
+            if(prefixPos == infixPos) prefixPos = infixPos + 1;
+            data[i] = new String[]{ list.subList(0, infixPos).stream().collect(Collectors.toStringJoiner("")).toString(),
+                    list.subList(infixPos, prefixPos).stream().collect(Collectors.toStringJoiner("")).toString(),
+                    list.subList(prefixPos, list.size()).stream().collect(Collectors.toStringJoiner("")).toString()
+            };
+        }
+        return data;
+    }
+
+    @Test(dataProvider = "Connector-Provider")
+    public void constructorTest(String INFIX, String PREFIX, String SUFFIX) {
+        //Test constructor with only infix
+        //String[] sj = notAlphanumeric();
+        String[] rndStrings = randomStringArray();
+        final StringJoiner nofixsj = new StringJoiner(INFIX);
+        Arrays.stream(rndStrings).forEach(t -> {nofixsj.add(t); });
+        String longStr1 = nofixsj.toString();
+        int index = 0;
+        int pos = 0;
+        while(index < rndStrings.length) {
+            if(index < rndStrings.length - 1) {
+                assertEquals(longStr1.substring(pos, pos + rndStrings[index].length()), rndStrings[index]);
+                pos += rndStrings[index++].length();
+                assertEquals(longStr1.substring(pos, pos + INFIX.length()), INFIX);
+                pos += INFIX.length();
+            } else
+                assertEquals(longStr1.substring(pos, pos + rndStrings[index].length()), rndStrings[index++]);
+        }
+
+        //Test constructor with infix, prefix and suffix
+        final StringJoiner hasfixsj = new StringJoiner(INFIX, PREFIX, SUFFIX);
+        Arrays.stream(rndStrings).forEach(t -> {hasfixsj.add(t); });
+        String longStr2 = hasfixsj.toString();
+        index = 0;
+        pos = 0;
+        assertEquals(longStr2.substring(pos, pos + PREFIX.length()), PREFIX);
+        pos += PREFIX.length();
+        while(index < rndStrings.length) {
+            if(index < rndStrings.length - 1) {
+                assertEquals(longStr2.substring(pos, pos + rndStrings[index].length()), rndStrings[index]);
+                pos += rndStrings[index++].length();
+                assertEquals(longStr2.substring(pos, pos + INFIX.length()), INFIX);
+                pos += INFIX.length();
+            } else {
+                assertEquals(longStr2.substring(pos, pos + rndStrings[index].length()), rndStrings[index]);
+                pos += rndStrings[index++].length();
+            }
+        }
+        assertEquals(longStr2.substring(pos, pos + SUFFIX.length()), SUFFIX);
+    }
+
+    @Test(dataProvider = "Connector-Provider")
+    public void addTest(String INFIX, String PREFIX, String SUFFIX) {
+        StringJoiner nofixsj = new StringJoiner(INFIX);
+        String randAddStr1 = StringUtilities.randomAlphabetic(rnd.nextInt(STRING_LEN));
+        assertEquals(nofixsj.add(randAddStr1).toString(), randAddStr1);
+        String randAddStr2 = StringUtilities.randomAlphabetic(rnd.nextInt(STRING_LEN));
+        assertEquals(nofixsj.add(randAddStr2).toString(), randAddStr1 + INFIX + randAddStr2);
+
+        //Test constructor with infix, prefix and suffix
+        StringJoiner hasfixsj = new StringJoiner(INFIX, PREFIX, SUFFIX);
+        assertEquals(hasfixsj.add(randAddStr1).toString(), PREFIX + randAddStr1 + SUFFIX);
+        assertEquals(hasfixsj.add(randAddStr2).toString(), PREFIX + randAddStr1 + INFIX + randAddStr2 + SUFFIX);
+    }
+
+    @Test(dataProvider = "Connector-Provider")
+    public void testSetEmptyOutput(String INFIX, String PREFIX, String SUFFIX) {
+        StringJoiner nofixsj = new StringJoiner(INFIX);
+        String emptyExpectedStr = StringUtilities.randomAlphabetic(rnd.nextInt(STRING_LEN));
+        assertEquals(nofixsj.toString().length(), 0);
+        nofixsj.setEmptyOutput(emptyExpectedStr);
+        assertEquals(nofixsj.toString(), emptyExpectedStr);
+        String randAddStr = StringUtilities.randomAlphabetic(rnd.nextInt(STRING_LEN));
+        assertEquals(nofixsj.add(randAddStr).toString(), randAddStr);
+
+        //Test constructor with infix, prefix and suffix
+        StringJoiner hasfixsj = new StringJoiner(INFIX, PREFIX, SUFFIX);
+        assertEquals(hasfixsj.toString(), PREFIX + SUFFIX);
+        hasfixsj.setEmptyOutput(emptyExpectedStr);
+        assertEquals(hasfixsj.toString(), emptyExpectedStr);
+
+        assertEquals(hasfixsj.add(randAddStr).toString(), PREFIX + randAddStr + SUFFIX);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/StringUtilities.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ *
+ * @summary utilities class supporting common operation for tests.
+ * @(#)StringUtilities.java
+ * @author Tristan Yan
+ * @version 1.0
+ */
+
+import java.util.Random;
+
+public class StringUtilities {
+    private final static Random RANDOM =  new Random(System.currentTimeMillis());
+
+    public static String randomString(int max_length, int min_length){
+        return randomAscii(min_length + RANDOM.nextInt(max_length - min_length));
+    }
+
+    public static String random(int count, int start, int end, boolean letters,
+            boolean numbers, char[] chars, Random rnd) {
+        if (count == 0) {
+            return "";
+        } else if (count < 0) {
+            throw new IllegalArgumentException("Requested random string length " + count + " is less than 0.");
+        }
+        if ((start == 0) && (end == 0)) {
+            end = 'z' + 1;
+            start = ' ';
+            if (!letters && !numbers) {
+                start = 0;
+                end = Integer.MAX_VALUE;
+            }
+        }
+
+        char[] buffer = new char[count];
+        int gap = end - start;
+
+        while (count-- != 0) {
+            char ch;
+            if (chars == null) {
+                ch = (char) (rnd.nextInt(gap) + start);
+            } else {
+                ch = chars[rnd.nextInt(gap) + start];
+            }
+            if ((letters && Character.isLetter(ch))
+                || (numbers && Character.isDigit(ch))
+                || (!letters && !numbers))
+            {
+                if(ch >= 56320 && ch <= 57343) {
+                    if(count == 0) {
+                        count++;
+                    } else {
+                        // low surrogate, insert high surrogate after putting it in
+                        buffer[count] = ch;
+                        count--;
+                        buffer[count] = (char) (55296 + rnd.nextInt(128));
+                    }
+                } else if(ch >= 55296 && ch <= 56191) {
+                    if(count == 0) {
+                        count++;
+                    } else {
+                        // high surrogate, insert low surrogate before putting it in
+                        buffer[count] = (char) (56320 + rnd.nextInt(128));
+                        count--;
+                        buffer[count] = ch;
+                    }
+                } else if(ch >= 56192 && ch <= 56319) {
+                    // private high surrogate, no effing clue, so skip it
+                    count++;
+                } else {
+                    buffer[count] = ch;
+                }
+            } else {
+                count++;
+            }
+        }
+        return new String(buffer);
+    }
+    public static String random(int count) {
+        return random(count, false, false);
+    }
+
+    public static String randomAscii(int count) {
+        return random(count, 32, 127, false, false);
+    }
+
+    public static String randomAlphabetic(int count) {
+        return random(count, true, false);
+    }
+
+    public static String randomAlphanumeric(int count) {
+        return random(count, true, true);
+    }
+
+    public static String randomNumeric(int count) {
+        return random(count, false, true);
+    }
+
+    public static String random(int count, boolean letters, boolean numbers) {
+        return random(count, 0, 0, letters, numbers);
+    }
+
+    public static String random(int count, int start, int end, boolean letters, boolean numbers) {
+        return random(count, start, end, letters, numbers, null, RANDOM);
+    }
+
+    public static String random(int count, int start, int end, boolean letters, boolean numbers, char[] chars) {
+        return random(count, start, end, letters, numbers, chars, RANDOM);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/AtomicInteger/UpdateAndGetTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary test AtomicInteger.updateAndGet()/getAndUpdate();
+ * @(#) UpdateAndGetTest.java
+ * @library ../../
+ * @author Tristan Yan
+ * @bug 8001666
+ * @run testng UpdateAndGetTest
+ */
+
+import java.util.Random;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.atomic.AtomicInteger;
+import static org.testng.Assert.*;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class UpdateAndGetTest {
+    private static Random rand = new Random(System.currentTimeMillis());
+
+    private final static int MAX_VALUE = 1 << 24;
+
+    private final static int MIN_VALUE = -1 << 24;
+
+    private final static int OP_TIMES = 1 << 10;
+
+    private final static int THREAD_NUM = 1 << 4;
+
+    @DataProvider
+    public Object[][] booleanProvider(){
+        return new Object[][]{
+            {Boolean.TRUE},
+            {Boolean.FALSE}
+        };
+    }
+
+    @Test(dataProvider = "booleanProvider")
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public void testUpdateAndGet(final boolean updateAndGet) throws InterruptedException,
+            ExecutionException {
+        int initValue = MIN_VALUE + rand.nextInt(MAX_VALUE - MIN_VALUE);
+        final AtomicInteger ai = new AtomicInteger(initValue);
+        final int randPlus = MIN_VALUE + rand.nextInt(MAX_VALUE - MIN_VALUE);
+        final int randMinus = MIN_VALUE + rand.nextInt(MAX_VALUE - MIN_VALUE);
+        if(updateAndGet) {
+            assertEquals(ai.updateAndGet(LambdaUtilities.addIntUnaryOperator(randPlus))
+                    , initValue + randPlus);
+            assertEquals(ai.updateAndGet(LambdaUtilities.subIntUnaryOperator(randMinus))
+                    , initValue + randPlus - randMinus);
+        } else {
+            assertEquals(ai.getAndUpdate(LambdaUtilities.addIntUnaryOperator(randPlus))
+                    , initValue);
+            assertEquals(ai.getAndUpdate(LambdaUtilities.subIntUnaryOperator(randMinus))
+                    , initValue + randPlus);
+        }
+        assertEquals(ai.get(), initValue + randPlus - randMinus);
+
+        ai.set(initValue);
+        Callable<Integer> ac = new Callable<Integer>(){
+            @Override
+            public Integer call() throws Exception {
+                int plusTimes1 = 0;
+                for(int index = 0; index < OP_TIMES; index++) {
+                    boolean plus = rand.nextBoolean();
+                    if(plus) plusTimes1++;
+                    if(updateAndGet)
+                        ai.updateAndGet(plus ?
+                                LambdaUtilities.addIntUnaryOperator(randPlus) :
+                                LambdaUtilities.subIntUnaryOperator(randMinus));
+                    else
+                        ai.getAndUpdate(plus ?
+                                LambdaUtilities.addIntUnaryOperator(randPlus) :
+                                LambdaUtilities.subIntUnaryOperator(randMinus));
+                }
+                return plusTimes1;
+            }
+
+        };
+        FutureTask[] futures = new FutureTask[THREAD_NUM -1];
+        for(int i = 0; i < THREAD_NUM -1; i++) {
+            futures[i] = new FutureTask<Integer>(ac);
+            new Thread(futures[i]).start();
+        }
+
+        int plusTimes = 0;
+        for(int index = 0; index < OP_TIMES; index++) {
+            boolean plus = rand.nextBoolean();
+            if(plus) plusTimes++;
+            if(updateAndGet)
+                ai.updateAndGet(plus ?
+                        LambdaUtilities.addIntUnaryOperator(randPlus) :
+                        LambdaUtilities.subIntUnaryOperator(randMinus));
+            else
+                ai.getAndUpdate(plus ?
+                        LambdaUtilities.addIntUnaryOperator(randPlus) :
+                        LambdaUtilities.subIntUnaryOperator(randMinus));
+        }
+        for(int i = 0; i < THREAD_NUM -1; i++) {
+            plusTimes += ((FutureTask<Integer>)futures[i]).get();
+        }
+        int expected = initValue + plusTimes * randPlus -
+                (THREAD_NUM * OP_TIMES - plusTimes) * randMinus;
+        assertEquals(expected, ai.get());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/AtomicIntegerFieldUpdater/UpdateAndGetTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+/**
+ * @test
+ * @summary test AtomicIntegerUpdateField.updateAndGet()/getAndUpdate();
+ * @(#) UpdateAndGetTest.java
+ * @library ../../
+ * @author Tristan Yan
+ * @run testng UpdateAndGetTest
+ * @bug 8001666
+ */
+
+import java.util.Random;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
+import static org.testng.Assert.*;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class UpdateAndGetTest {
+    private static Random rand = new Random(System.currentTimeMillis());
+
+    private final static int MAX_VALUE = 1 << 24;
+
+    private final static int MIN_VALUE = -1 << 24;
+
+    private final static int OP_TIMES = 1 << 10;
+
+    private final static int THREAD_NUM = 1 << 4;
+
+    @DataProvider
+    public Object[][] booleanProvider(){
+        return new Object[][]{
+            {Boolean.TRUE},
+            {Boolean.FALSE}
+        };
+    }
+
+    @Test(dataProvider = "booleanProvider")
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public void testUpdateAndGet(final boolean updateAndGet) throws InterruptedException,
+            ExecutionException {
+        final Updater u = new Updater();
+        final AtomicIntegerFieldUpdater<Updater> accAIFU = AtomicIntegerFieldUpdater.<Updater>newUpdater((Class<Updater>)(Class<?>)u.getClass(), "accumulation");
+        final int randPlus = MIN_VALUE + rand.nextInt(MAX_VALUE - MIN_VALUE);
+        final int randMinus = MIN_VALUE + rand.nextInt(MAX_VALUE - MIN_VALUE);
+        if(updateAndGet) {
+            assertEquals(accAIFU.updateAndGet(u, LambdaUtilities.addIntUnaryOperator(randPlus)), randPlus);
+            assertEquals(accAIFU.updateAndGet(u, LambdaUtilities.subIntUnaryOperator(randMinus)), randPlus - randMinus);
+        } else {
+            assertEquals(accAIFU.getAndUpdate(u, LambdaUtilities.addIntUnaryOperator(randPlus)), 0);
+            assertEquals(accAIFU.getAndUpdate(u, LambdaUtilities.subIntUnaryOperator(randMinus)), randPlus);
+        }
+        assertEquals(u.accumulation, randPlus - randMinus);
+
+        u.accumulation = 0;
+
+        Callable<Integer> ac = new Callable<Integer>(){
+            @Override
+            public Integer call() throws Exception {
+                int plusTimes = 0;
+                for(int index = 0; index < OP_TIMES; index++) {
+                    boolean plus = rand.nextBoolean();
+                    if(plus) plusTimes++;
+                    if(updateAndGet)
+                        accAIFU.updateAndGet(u, plus ?
+                                LambdaUtilities.addIntUnaryOperator(randPlus) :
+                                LambdaUtilities.subIntUnaryOperator(randMinus));
+                    else
+                        accAIFU.getAndUpdate(u, plus ?
+                                LambdaUtilities.addIntUnaryOperator(randPlus) :
+                                LambdaUtilities.subIntUnaryOperator(randMinus));
+                }
+                return plusTimes;
+            }
+        };
+
+        FutureTask[] futures = new FutureTask[THREAD_NUM -1];
+        for(int i = 0; i < THREAD_NUM -1; i++) {
+            futures[i] = new FutureTask<Integer>(ac);
+            new Thread(futures[i]).start();
+        }
+        int plusTimes = 0;
+        for(int index = 0; index < OP_TIMES; index++) {
+            boolean plus = rand.nextBoolean();
+            if(plus) plusTimes++;
+            if(updateAndGet)
+                accAIFU.updateAndGet(u, plus ?
+                        LambdaUtilities.addIntUnaryOperator(randPlus) :
+                        LambdaUtilities.subIntUnaryOperator(randMinus));
+            else
+                accAIFU.getAndUpdate(u, plus ?
+                        LambdaUtilities.addIntUnaryOperator(randPlus) :
+                        LambdaUtilities.subIntUnaryOperator(randMinus));
+        }
+        for(int i = 0; i < THREAD_NUM -1; i++) {
+            plusTimes += ((FutureTask<Integer>)futures[i]).get();
+        }
+        int expected = plusTimes * randPlus -
+                (THREAD_NUM * OP_TIMES - plusTimes) * randMinus;
+        assertEquals(expected, u.accumulation);
+    }
+
+    static class Updater{
+        public volatile int accumulation;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/AtomicLong/UpdateAndGetTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary test AtomicLong.updateAndGet()/getAndUpdate();
+ * @(#) UpdateAndGetTest.java
+ * @library ../../
+ * @author Tristan Yan
+ * @run testng UpdateAndGetTest
+ * @bug 8001666
+ */
+
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicLong;
+import static org.testng.Assert.*;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class UpdateAndGetTest {
+    private static Random rand = new Random(System.currentTimeMillis());
+
+    private final static int MAX_VALUE = 1 << 24;
+
+    private final static int MIN_VALUE = -1 << 24;
+
+    private final static int OP_TIMES = 1 << 10;
+
+    private final static int THREAD_NUM = 1 << 4;
+
+    @DataProvider
+    public Object[][] booleanProvider(){
+        return new Object[][]{
+            {Boolean.TRUE},
+            {Boolean.FALSE}
+        };
+    }
+
+    @Test(dataProvider = "booleanProvider")
+    public void testUpdateAndGet(final boolean updateAndGet) throws InterruptedException,
+            ExecutionException {
+        long initValue = rand.nextLong();
+        final AtomicLong al = new AtomicLong(initValue);
+        long tl1 = rand.nextLong();
+        if(((byte)(tl1 >> 63) & (byte)(initValue >> 63)) == 0){
+            if(initValue > 0) {
+                if(tl1 > Long.MAX_VALUE - initValue)
+                    tl1 = - tl1;
+            } else {
+                if(tl1 < Long.MIN_VALUE - initValue)
+                    tl1 = - tl1;
+            }
+        }
+        final long randPlus = tl1;
+
+        long tl2 = rand.nextLong();
+        if(((byte)(tl2 >> 63) & (byte)(initValue + randPlus >> 63)) == 1){
+            if(initValue + randPlus > 0) {
+                if(-tl2 > Long.MAX_VALUE - (initValue + randPlus))
+                    tl2 = - tl2;
+            } else {
+                if(tl2 < Long.MIN_VALUE + (initValue + randPlus))
+                    tl2 = - tl2;
+            }
+        }
+        final long randMinus = tl2;
+        if(updateAndGet) {
+            assertEquals(al.updateAndGet(LambdaUtilities.addLongUnaryOperator(randPlus))
+                    , initValue + randPlus);
+            assertEquals(al.updateAndGet(LambdaUtilities.subLongUnaryOperator(randMinus))
+                    , initValue + randPlus - randMinus);
+        } else {
+            assertEquals(al.getAndUpdate(LambdaUtilities.addLongUnaryOperator(randPlus))
+                    , initValue);
+            assertEquals(al.getAndUpdate(LambdaUtilities.subLongUnaryOperator(randMinus))
+                    , initValue + randPlus);
+        }
+        assertEquals(al.get() , initValue + randPlus - randMinus);
+
+        final long randPlus1 = rand.nextBoolean() ? (long)rand.nextInt(MAX_VALUE) : -(long)rand.nextInt(MAX_VALUE);
+        final long randMinus1 = rand.nextBoolean() ? (long)rand.nextInt(MAX_VALUE) : -(long)rand.nextInt(MAX_VALUE);
+        al.set(initValue);
+        final int mainPLusTimes = 0;
+        int minusPLusTimes = 0;
+
+        class UpdateThread  extends Thread{
+            OpTimes ops;
+            CountDownLatch latch;
+            UpdateThread(OpTimes ops, CountDownLatch latch){
+                this.ops = ops;
+                this.latch = latch;
+            }
+            @Override
+            public void run() {
+                int plusTimes = 0;
+                int minusTimes = 0;
+                for(int index = 0; index < OP_TIMES; index++) {
+                    boolean plus = rand.nextBoolean();
+                    if(plus) {
+                        if (randPlus1 > 0 && al.get() > Long.MAX_VALUE - randPlus1
+                                || randPlus1 < 0 && al.get() < Long.MIN_VALUE - randPlus1)
+                            continue;
+                    }
+                    else  {
+                        if (randPlus1 > 0 && al.get() < Long.MIN_VALUE + randPlus1
+                                || randPlus1 > 0 && al.get() > Long.MAX_VALUE - randPlus1)
+                            continue;
+                    }
+                    if(updateAndGet)
+                        al.updateAndGet(plus ?
+                                LambdaUtilities.addLongUnaryOperator(randPlus1) :
+                                LambdaUtilities.subLongUnaryOperator(randMinus1));
+                    else
+                        al.getAndUpdate(plus ?
+                                LambdaUtilities.addLongUnaryOperator(randPlus1) :
+                                LambdaUtilities.subLongUnaryOperator(randMinus1));
+                    if(plus)
+                        plusTimes++;
+                    else
+                        minusTimes++;
+                }
+                ops.plus = plusTimes;
+                ops.minus = minusTimes;
+                latch.countDown();
+            }
+
+        };
+        OpTimes[] opts = new OpTimes[THREAD_NUM -1];
+        CountDownLatch latch = new CountDownLatch(THREAD_NUM -1);
+        for(int i = 0; i < THREAD_NUM -1; i++) {
+            opts[i] = new OpTimes();
+            new UpdateThread(opts[i], latch).start();
+        }
+        int plusTimes = 0;
+        int minusTimes = 0;
+        for(int index = 0; index < OP_TIMES; index++) {
+            boolean plus = rand.nextBoolean();
+            if(plus) {
+                if (randPlus1 > 0 && al.get() > Long.MAX_VALUE - randPlus1
+                        || randPlus1 < 0 && al.get() < Long.MIN_VALUE - randPlus1)
+                    continue;
+            }
+            else  {
+                if (randPlus1 > 0 && al.get() < Long.MIN_VALUE + randPlus1
+                        || randPlus1 > 0 && al.get() > Long.MAX_VALUE - randPlus1)
+                    continue;
+            }
+            if(updateAndGet)
+                al.updateAndGet(plus ?
+                        LambdaUtilities.addLongUnaryOperator(randPlus1) :
+                        LambdaUtilities.subLongUnaryOperator(randMinus1));
+            else
+                al.getAndUpdate(plus ?
+                        LambdaUtilities.addLongUnaryOperator(randPlus1) :
+                        LambdaUtilities.subLongUnaryOperator(randMinus1));
+            if(plus)
+                plusTimes++;
+            else
+                minusTimes++;
+        }
+        latch.await();
+        for(int i = 0; i < THREAD_NUM -1; i++) {
+            plusTimes += opts[i].plus;
+            minusTimes += opts[i].minus;
+        }
+        long expected = initValue + plusTimes * randPlus1 -
+                minusTimes * randMinus1;
+        assertEquals(expected, al.get());
+    }
+}
+
+class OpTimes{
+    public int plus;
+
+    public int minus;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/AtomicLongFieldUpdater/UpdateAndGetTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary test AtomicLongFieldUpdater.updateAndGet()/getAndUpdate();
+ * @(#) UpdateAndGetTest.java
+ * @library ../../
+ * @author Tristan Yan
+ * @run testng UpdateAndGetTest
+ * @bug 8001666
+ */
+
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.atomic.AtomicLongFieldUpdater;
+import static org.testng.Assert.*;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class UpdateAndGetTest {
+    private static Random rand = new Random(System.currentTimeMillis());
+
+    private final static int OP_TIMES = 1 << 10;
+
+    private final static int THREAD_NUM = 1 << 4;
+
+    @DataProvider
+    public Object[][] booleanProvider(){
+        return new Object[][]{
+            {Boolean.TRUE},
+            {Boolean.FALSE}
+        };
+    }
+
+    @Test(dataProvider = "booleanProvider")
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public void testUpdateAndGet(final boolean updateAndGet) throws InterruptedException,
+            ExecutionException {
+        long initValue = rand.nextLong();
+        final Updater u = new Updater();
+        u.accumulation = initValue;
+        final AtomicLongFieldUpdater<Updater> accAIFU = AtomicLongFieldUpdater.<Updater>newUpdater((Class<Updater>)(Class<?>)u.getClass(), "accumulation");
+        final long randPlus = rand.nextLong();
+        final long randMinus = rand.nextLong();
+        if(updateAndGet) {
+            assertEquals(accAIFU.updateAndGet(u, LambdaUtilities.addLongUnaryOperator(randPlus)), initValue + randPlus);
+            assertEquals(accAIFU.updateAndGet(u, LambdaUtilities.subLongUnaryOperator(randMinus)), initValue + randPlus - randMinus);
+        } else {
+            assertEquals(accAIFU.getAndUpdate(u, LambdaUtilities.addLongUnaryOperator(randPlus)), initValue);
+            assertEquals(accAIFU.getAndUpdate(u, LambdaUtilities.subLongUnaryOperator(randMinus)), initValue + randPlus);
+        }
+        assertEquals(u.accumulation, initValue + randPlus - randMinus);
+
+        class UpdateThread  extends Thread{
+            OpTimes ops;
+
+            CountDownLatch latch;
+            UpdateThread(OpTimes ops, CountDownLatch latch){
+                this.ops = ops;
+                this.latch = latch;
+            }
+            @Override
+            public void run() {
+                int plusTimes = 0;
+                int minusTimes = 0;
+                for(int index = 0; index < OP_TIMES; index++) {
+                    boolean plus = rand.nextBoolean();
+                    if(updateAndGet)
+                        accAIFU.updateAndGet(u, plus ?
+                                LambdaUtilities.addLongUnaryOperator(randPlus) :
+                                LambdaUtilities.subLongUnaryOperator(randMinus));
+                    else
+                        accAIFU.getAndUpdate(u, plus ?
+                                LambdaUtilities.addLongUnaryOperator(randPlus) :
+                                LambdaUtilities.subLongUnaryOperator(randMinus));
+                    if(plus)
+                        plusTimes++;
+                    else
+                        minusTimes++;
+                }
+                ops.plus = plusTimes;
+                ops.minus = minusTimes;
+                latch.countDown();
+            }
+        };
+        u.accumulation = initValue;
+
+        int plusTimes = 0;
+        int minusTimes = 0;
+        OpTimes[] opts = new OpTimes[THREAD_NUM -1];
+        CountDownLatch latch = new CountDownLatch(THREAD_NUM -1);
+        for(int i = 0; i < THREAD_NUM -1; i++) {
+            opts[i] = new OpTimes();
+            new UpdateThread(opts[i], latch).start();
+        }
+
+        for(int index = 0; index < OP_TIMES; index++) {
+            boolean plus = rand.nextBoolean();
+            if(updateAndGet)
+                accAIFU.updateAndGet(u, plus ?
+                        LambdaUtilities.addLongUnaryOperator(randPlus) :
+                        LambdaUtilities.subLongUnaryOperator(randMinus));
+            else
+                accAIFU.getAndUpdate(u, plus ?
+                        LambdaUtilities.addLongUnaryOperator(randPlus) :
+                        LambdaUtilities.subLongUnaryOperator(randMinus));
+            if(plus)
+                plusTimes++;
+            else
+                minusTimes++;
+        }
+        latch.await();
+        for(int i = 0; i < THREAD_NUM -1; i++) {
+            plusTimes += opts[i].plus;
+            minusTimes += opts[i].minus;
+        }
+        long expected = initValue + plusTimes * randPlus -
+                minusTimes * randMinus;
+        assertEquals(expected, u.accumulation);
+    }
+
+    static class Updater{
+        public volatile long accumulation;
+    }
+
+    static class OpTimes{
+        public int plus;
+
+        public int minus;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/AtomicReference/UpdateAndGetTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary test AtomicReference.updateAndGet()/getAndUpdate();
+ * @(#) UpdateAndGetTest.java
+ * @library ../../
+ * @author Tristan Yan
+ * @run testng UpdateAndGetTest
+ * @bug 8001666
+ */
+
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.UnaryOperator;
+import static org.testng.Assert.*;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class UpdateAndGetTest {
+    private static Random rand = new Random(System.currentTimeMillis());
+
+    private final static int OP_TIMES = 1 << 10;
+
+    private final static int THREAD_NUM = 1 << 4;
+
+    @DataProvider
+    public Object[][] booleanProvider(){
+        return new Object[][]{
+            {Boolean.TRUE},
+            {Boolean.FALSE}
+        };
+    }
+
+    @Test(dataProvider = "booleanProvider")
+    public void testUpdateAndGet(final boolean updateAndGet) throws InterruptedException{
+        int initPlus = rand.nextInt();
+        int initMinus = rand.nextInt();
+        final AtomicReference<OpValues> ar
+                = new AtomicReference<>(new OpValues(initPlus, initMinus));
+        final int oprnd = rand.nextInt();
+        boolean startFromPlus = rand.nextBoolean();
+        if(updateAndGet) {
+            assertEquals(ar.updateAndGet(opUnaryOperator(startFromPlus, oprnd))
+                    , startFromPlus ? new OpValues(initPlus + oprnd, initMinus) :
+                    new OpValues(initPlus, initMinus - oprnd));
+            assertEquals(ar.updateAndGet(opUnaryOperator(!startFromPlus, oprnd))
+                    , new OpValues(initPlus + oprnd, initMinus - oprnd));
+        } else {
+            assertEquals(ar.getAndUpdate(opUnaryOperator(startFromPlus, oprnd))
+                    , new OpValues(initPlus, initMinus));
+            assertEquals(ar.getAndUpdate(opUnaryOperator(!startFromPlus, oprnd))
+                    ,  startFromPlus ? new OpValues(initPlus + oprnd, initMinus) :
+                    new OpValues(initPlus, initMinus - oprnd));
+        }
+        class UpdateThread  extends Thread{
+            CountDownLatch latch;
+            private int plusTimes = 0;
+            private int minusTimes = 0;
+
+            UpdateThread(CountDownLatch latch){
+                this.latch = latch;
+            }
+            @Override
+            public void run() {
+                for(int index = 0; index < OP_TIMES; index++) {
+                    boolean plus = rand.nextBoolean();
+                    if(updateAndGet)
+                        ar.updateAndGet(opUnaryOperator(plus, oprnd));
+                    else
+                        ar.getAndUpdate(opUnaryOperator(plus, oprnd));
+                    if(plus)
+                        plusTimes++;
+                    else
+                        minusTimes++;
+                }
+                latch.countDown();
+            }
+            int plusTimes(){ return plusTimes; }
+            int minusTimes(){ return minusTimes; }
+        };
+        UpdateThread[] threads = new UpdateThread[THREAD_NUM -1];
+        CountDownLatch latch = new CountDownLatch(THREAD_NUM -1);
+        for(int i = 0; i < THREAD_NUM -1; i++) {
+            threads[i] = new UpdateThread(latch);
+            threads[i].start();
+        }
+        int plusTimes = 0;
+        int minusTimes = 0;
+        for(int index = 0; index < OP_TIMES; index++) {
+            boolean isPlus = rand.nextBoolean();
+            if(updateAndGet)
+                ar.updateAndGet(opUnaryOperator(isPlus, oprnd));
+            else
+                ar.getAndUpdate(opUnaryOperator(isPlus, oprnd));
+            if(isPlus)
+                plusTimes++;
+            else
+                minusTimes++;
+        }
+        latch.await();
+        for(int i = 0; i < THREAD_NUM -1; i++) {
+            plusTimes += threads[i].plusTimes();
+            minusTimes += threads[i].minusTimes();
+        }
+        assertEquals(ar.get().getPlusAccumulated(), initPlus + plusTimes * oprnd + oprnd);
+        assertEquals(ar.get().getMinusAccumulated(), initMinus - minusTimes * oprnd - oprnd);
+    }
+
+    static final class OpValues{
+        final int plusAccumulated;
+
+        final int minusAccumulated;
+
+        OpValues(int plusAccumulated, int minusAccumulated){
+            this.plusAccumulated = plusAccumulated;
+            this.minusAccumulated = minusAccumulated;
+        }
+
+        OpValues operate(boolean isPlus, int value) {
+            if(isPlus)
+                return new OpValues(plusAccumulated + value, minusAccumulated);
+            else
+                return new OpValues(plusAccumulated, minusAccumulated - value);
+        }
+
+        int getPlusAccumulated(){    return plusAccumulated;  }
+        int getMinusAccumulated(){    return minusAccumulated;  }
+
+        @Override
+        public boolean equals(Object o){
+            OpValues opv = (OpValues)o;
+            return (opv.plusAccumulated == plusAccumulated)
+                    && (opv.minusAccumulated == minusAccumulated);
+        }
+    }
+
+    public static UnaryOperator<OpValues> opUnaryOperator(boolean isPlus, int value) {
+        return t -> t.operate(isPlus, value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/concurrent/AtomicReferenceFieldUpdater/UpdateAndGetTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary test AtomicReferenceFieldUpdater.updateAndGet()/getAndUpdate();
+ * @(#) UpdateAndGetTest.java
+ * @library ../../
+ * @author Tristan Yan
+ * @run testng UpdateAndGetTest
+ * @bug 8001666
+ */
+
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+import java.util.function.UnaryOperator;
+import static org.testng.Assert.*;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+public class UpdateAndGetTest {
+    private static Random rand = new Random(System.currentTimeMillis());
+
+    private final static int OP_TIMES = 1 << 10;
+
+    private final static int THREAD_NUM = 1 << 4;
+
+    @DataProvider
+    public Object[][] booleanProvider(){
+        return new Object[][]{
+            {Boolean.TRUE},
+            {Boolean.FALSE}
+        };
+    }
+
+    @Test(dataProvider = "booleanProvider")
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public void testUpdateAndGet(final boolean updateAndGet) throws InterruptedException{
+        int initValue = rand.nextInt();
+        final Updater u = new Updater();
+        u.accumulation = new OpValues(initValue);
+        final AtomicReferenceFieldUpdater<Updater, OpValues> accARFU
+                = AtomicReferenceFieldUpdater.<Updater, OpValues>newUpdater((Class<Updater>)(Class<?>)u.getClass(), (Class<OpValues>)(Class<?>)u.accumulation.getClass(),  "accumulation");
+
+        final int oprnd = rand.nextInt();
+        boolean startFromPlus = rand.nextBoolean();
+        if(updateAndGet) {
+            assertEquals(accARFU.updateAndGet(u,opUnaryOperator(startFromPlus, oprnd))
+                    , new OpValues(startFromPlus ? initValue + oprnd : initValue - oprnd));
+            assertEquals(accARFU.updateAndGet(u,opUnaryOperator(!startFromPlus, oprnd))
+                    , new OpValues(initValue));
+        } else {
+            assertEquals(accARFU.getAndUpdate(u,opUnaryOperator(startFromPlus, oprnd))
+                    , new OpValues(initValue));
+            assertEquals(accARFU.getAndUpdate(u,opUnaryOperator(!startFromPlus, oprnd))
+                    , new OpValues(startFromPlus ? initValue + oprnd : initValue - oprnd));
+        }
+        class UpdateThread  extends Thread{
+            CountDownLatch latch;
+            private int plusTimes = 0;
+            private int minusTimes = 0;
+
+            UpdateThread(CountDownLatch latch){
+                this.latch = latch;
+            }
+            @Override
+            public void run() {
+                for(int index = 0; index < OP_TIMES; index++) {
+                    boolean plus = rand.nextBoolean();
+                    if(updateAndGet)
+                        accARFU.updateAndGet(u,opUnaryOperator(plus, oprnd));
+                    else
+                        accARFU.getAndUpdate(u,opUnaryOperator(plus, oprnd));
+                    if(plus)
+                        plusTimes++;
+                    else
+                        minusTimes++;
+                }
+                latch.countDown();
+            }
+            int plusTimes(){ return plusTimes; }
+            int minusTimes(){ return minusTimes; }
+        };
+        UpdateThread[] threads = new UpdateThread[THREAD_NUM -1];
+        CountDownLatch latch = new CountDownLatch(THREAD_NUM -1);
+        for(int i = 0; i < THREAD_NUM -1; i++) {
+            threads[i] = new UpdateThread(latch);
+            threads[i].start();
+        }
+        int plusTimes = 0;
+        int minusTimes = 0;
+        for(int index = 0; index < OP_TIMES; index++) {
+            boolean isPlus = rand.nextBoolean();
+            if(updateAndGet)
+                accARFU.updateAndGet(u,opUnaryOperator(isPlus, oprnd));
+            else
+                accARFU.getAndUpdate(u,opUnaryOperator(isPlus, oprnd));
+            if(isPlus)
+                plusTimes++;
+            else
+                minusTimes++;
+        }
+        latch.await();
+        for(int i = 0; i < THREAD_NUM -1; i++) {
+            plusTimes += threads[i].plusTimes();
+            minusTimes += threads[i].minusTimes();
+        }
+        assertEquals(accARFU.get(u).getAccumulated(), initValue + plusTimes * oprnd - minusTimes * oprnd);
+    }
+
+    public UpdateAndGetTest() {
+    }
+    static final class OpValues{
+        int accumulated;
+
+        OpValues(int accumulated){
+            this.accumulated = accumulated;
+        }
+
+        OpValues operate(boolean isPlus, int value) {
+            if(isPlus)
+                return new OpValues(accumulated + value);
+            else
+                return new OpValues(accumulated - value);
+        }
+
+        int getAccumulated(){    return accumulated;  }
+
+        @Override
+        public boolean equals(Object o){
+            OpValues opv = (OpValues)o;
+            return (opv.accumulated == accumulated);
+        }
+    }
+
+
+    static class Updater{
+        public volatile OpValues accumulation;
+    }
+
+    public static UnaryOperator<OpValues> opUnaryOperator(boolean isPlus, int value) {
+        return t -> t.operate(isPlus, value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/stream/Stream/EmployeeStreamTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,1065 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Basic test for Stream<Employee>
+ * @library ../..
+ * @(#) EmployeeStreamTest.java
+ * @author Eric Wang/Tristan Yan
+ * @run testng EmployeeStreamTest
+ */
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiConsumer;
+import java.util.function.BiFunction;
+import java.util.function.Predicate;
+import java.util.function.Predicates;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.Streams;
+import static org.testng.Assert.*;
+import org.testng.ITest;
+import org.testng.annotations.*;
+
+class Employee implements Comparable<Employee>, Cloneable {
+    static enum Title {
+        IC1, IC2, IC3, IC4
+    }
+
+    static enum Rule {
+        ID {
+            String getValue(Employee e) {
+                return e.id;
+            }
+
+            Comparator<Employee> getComparator() {
+                return (o1, o2) -> o1.id.compareTo(o2.id);
+            }
+        },
+        AGE {
+            Integer getValue(Employee e) {
+                return e.age;
+            }
+
+            Comparator<Employee> getComparator() {
+                return (o1, o2) -> Integer.valueOf(o1.age).compareTo(o2.age);
+            }
+        },
+        MALE {
+            Boolean getValue(Employee e) {
+                return e.male;
+            }
+
+            Comparator<Employee> getComparator() {
+                return (o1, o2) -> Boolean.valueOf(o1.male).compareTo(o2.male);
+            }
+        },
+        SALARY {
+            Float getValue(Employee e) {
+                return e.salary;
+            }
+
+            Comparator<Employee> getComparator() {
+                return (o1, o2) -> Float.valueOf(o1.salary).compareTo(o2.salary);
+            }
+        },
+        TITLE {
+            Title getValue(Employee e) {
+                return e.title;
+            }
+
+            Comparator<Employee> getComparator() {
+                return (o1, o2) -> Integer.valueOf(o1.title.ordinal()).compareTo(o2.title.ordinal());
+            }
+        };
+
+        abstract Comparator<Employee> getComparator();
+
+        abstract Object getValue(Employee e);
+    }
+
+    String id = null;
+    int age = 0;
+    boolean male = false;
+    float salary = 0;
+    Title title = null;
+    static final int MIN_ID = 5;
+    static final int MAX_ID = 10;
+    static final int MIN_AGE = 18;
+    static final int MAX_AGE = 65;
+    static final int MIN_SALARY = 1000;
+    static final int MAX_SALARY = 100000;
+
+    @Override
+    public boolean equals(Object other) {
+        if (other instanceof Employee) {
+            return this.id.equals(((Employee) other).id);
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int compareTo(Employee t) {
+        return this.id.compareTo(t.id);
+    }
+
+    @Override
+    public int hashCode() {
+        return this.id.hashCode();
+    }
+
+    @Override
+    public Employee clone() {
+        Employee e = new Employee();
+        e.age = this.age;
+        e.id = this.id;
+        e.male = this.male;
+        e.salary = this.salary;
+        e.title = this.title;
+        return e;
+    }
+
+    @Override
+    public String toString() {
+        return "id=" + id + ", age=" + age + ". male=" + male + ", salary=" + salary + ", title=" + title;
+    }
+}
+
+public class EmployeeStreamTest<T extends Collection<Employee>> implements ITest {
+
+    enum ParallelType {
+        Parallel, Sequential, Default
+    };
+
+    private final static int DATA_SIZE = 1 << 10;
+
+    private final static Random rand = new Random(System.currentTimeMillis());
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private static Class[] defaultConstructorClazz = { (Class<ArrayDeque<Employee>>) (Class<?>) (ArrayDeque.class),
+            (Class<ArrayList<Employee>>) (Class<?>) (ArrayList.class),
+            (Class<ConcurrentLinkedDeque<Employee>>) (Class<?>) (ConcurrentLinkedDeque.class),
+            (Class<ConcurrentLinkedQueue<Employee>>) (Class<?>) (ConcurrentLinkedQueue.class),
+            (Class<ConcurrentSkipListSet<Employee>>) (Class<?>) (ConcurrentSkipListSet.class),
+            (Class<CopyOnWriteArrayList<Employee>>) (Class<?>) (CopyOnWriteArrayList.class),
+            (Class<HashSet<Employee>>) (Class<?>) (HashSet.class),
+            (Class<LinkedBlockingDeque<Employee>>) (Class<?>) (LinkedBlockingDeque.class),
+            (Class<LinkedBlockingQueue<Employee>>) (Class<?>) (LinkedBlockingQueue.class),
+            (Class<LinkedHashSet<Employee>>) (Class<?>) (LinkedHashSet.class),
+            (Class<LinkedList<Employee>>) (Class<?>) (LinkedList.class),
+            (Class<LinkedTransferQueue<Employee>>) (Class<?>) (LinkedTransferQueue.class),
+            (Class<PriorityBlockingQueue<Employee>>) (Class<?>) (PriorityBlockingQueue.class),
+            (Class<PriorityQueue<Employee>>) (Class<?>) (PriorityQueue.class),
+            (Class<Stack<Employee>>) (Class<?>) (Stack.class), (Class<TreeSet<Employee>>) (Class<?>) (TreeSet.class),
+            (Class<Vector<Employee>>) (Class<?>) (Vector.class)
+    };
+
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private static Class[] capacityConstructorClazz = {
+            (Class<ArrayBlockingQueue<Employee>>) (Class<?>) (ArrayBlockingQueue.class),
+            (Class<ArrayDeque<Employee>>) (Class<?>) (ArrayDeque.class),
+            (Class<ArrayList<Employee>>) (Class<?>) (ArrayList.class),
+            (Class<HashSet<Employee>>) (Class<?>) (HashSet.class),
+            (Class<LinkedBlockingDeque<Employee>>) (Class<?>) (LinkedBlockingDeque.class),
+            (Class<LinkedBlockingQueue<Employee>>) (Class<?>) (LinkedBlockingQueue.class),
+            (Class<LinkedHashSet<Employee>>) (Class<?>) (LinkedHashSet.class),
+            (Class<PriorityBlockingQueue<Employee>>) (Class<?>) (PriorityBlockingQueue.class),
+            (Class<PriorityQueue<Employee>>) (Class<?>) (PriorityQueue.class),
+            (Class<Vector<Employee>>) (Class<?>) (Vector.class) };
+
+    private Class<T> typeObject;
+
+    private boolean hasIni;
+
+    private int initSize;
+
+    public EmployeeStreamTest(Class<T> clazz, int... initSizes) {
+        this.typeObject = clazz;
+        assert (initSizes.length <= 1);
+        if (initSizes.length == 1) {
+            hasIni = true;
+            this.initSize = initSizes[0];
+        }
+    }
+
+    @Factory
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    public static Object[] create(){
+        List<EmployeeStreamTest> result = new ArrayList<>();
+        Stream<Class> stream1 = Arrays.stream(defaultConstructorClazz);
+        Stream<Class> stream2 = Arrays.stream(capacityConstructorClazz);
+        stream1.forEach(clazz -> result.add(new EmployeeStreamTest(clazz)));
+        stream2.forEach(clazz -> result.add(new EmployeeStreamTest(clazz,
+                DATA_SIZE)));
+        return result.toArray();
+    }
+
+    @Override
+    public String getTestName() {
+        return typeObject.getName() + "<Employee>";
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testAllMatch() throws Exception {
+        Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+        while (iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Employee> c1 = generateData(DATA_SIZE);
+           Employee.Rule rule = Employee.Rule.values()[rand.nextInt(Employee.Rule.values().length)];
+            Employee limit = generateData();
+            limit.salary = rand.nextFloat() * (Employee.MAX_SALARY * 2);
+            limit.age = rand.nextInt(Employee.MAX_AGE * 2);
+            boolean isUP = rand.nextBoolean();
+            Stream<Employee> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream()
+                    : (type == ParallelType.Sequential) ? c1.stream().sequential() : c1.stream();
+            assertEquals(stream1.allMatch(LambdaUtilities.randomGenericPredicate(isUP, limit, rule.getComparator())),
+                    verifyMatch(c1, limit, isUP, true, rule));
+
+            // Empty stream's allMatch will return true always
+            @SuppressWarnings("cast")
+            Collection<Employee> emptyCol = hasIni ?
+                    (Collection<Employee>) LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Employee>) LambdaUtilities.create(typeObject);
+            Stream<Employee> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream()
+                    : (type == ParallelType.Sequential) ? emptyCol.stream().sequential() : emptyCol.stream();
+            assertTrue(stream2.allMatch(LambdaUtilities.randomGenericPredicate(isUP, limit, rule.getComparator())));
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testAnyMatch() throws Exception {
+        Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+        while (iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Employee> c1 = generateData(DATA_SIZE);
+            Employee.Rule rule = Employee.Rule.values()[rand.nextInt(Employee.Rule.values().length)];
+            Employee limit = generateData();
+            limit.salary = rand.nextFloat() * (Employee.MAX_SALARY * 2);
+            limit.age = rand.nextInt(Employee.MAX_AGE * 2);
+            boolean isUP = rand.nextBoolean();
+            Stream<Employee> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream()
+                    : (type == ParallelType.Sequential) ? c1.stream().sequential() : c1.stream();
+            assertEquals(stream1.anyMatch(LambdaUtilities.randomGenericPredicate(isUP, limit, rule.getComparator())),
+                    verifyMatch(c1, limit, isUP, false, rule));
+
+            // Empty stream's anyMatch, noneMatch will return false always
+            @SuppressWarnings("cast")
+            Collection<Employee> emptyCol = hasIni ? (Collection<Employee>) LambdaUtilities
+                    .create(typeObject, initSize) : (Collection<Employee>) LambdaUtilities.create(typeObject);
+            Stream<Employee> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream()
+                    : (type == ParallelType.Sequential) ? emptyCol.stream().sequential() : emptyCol.stream();
+            assertTrue(!stream2.anyMatch(LambdaUtilities.randomGenericPredicate(isUP, limit, rule.getComparator())));
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testConcat() throws Exception {
+        Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+        while (iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Employee> l1 = generateData(DATA_SIZE);
+            Collection<Employee> l2 = generateData(DATA_SIZE);
+           Employee.Rule rule = Employee.Rule.values()[rand.nextInt(Employee.Rule.values().length)];
+            Employee limit = generateData();
+            limit.salary = rand.nextFloat() * (Employee.MAX_SALARY * 2);
+            limit.age = rand.nextInt(Employee.MAX_AGE * 2);
+            boolean isUP = rand.nextBoolean();
+            Predicate<Employee> p = LambdaUtilities.randomGenericPredicate(isUP, limit, rule.getComparator());
+
+            Stream<Employee> stream11 = (type == ParallelType.Parallel) ? l1.parallelStream()
+                    : (type == ParallelType.Sequential) ? l1.stream().sequential() : l1.stream();
+            Stream<Employee> stream21 = (type == ParallelType.Parallel) ? l2.parallelStream()
+                    : (type == ParallelType.Sequential) ? l2.stream().sequential() : l2.stream();
+
+            Collection<Employee> result1 = stream11.filter(p).collect(Collectors.toCollection(LinkedList<Employee>::new));
+            Collection<Employee> result2 = stream21.filter(p).collect(Collectors.toCollection(LinkedList<Employee>::new));
+            result1.addAll(result2);
+
+            Collection<Employee> expectedResult = hasIni ? LambdaUtilities.create(typeObject, initSize << 1)
+                    : LambdaUtilities.create(typeObject);
+            Stream<Employee> stream12 = (type == ParallelType.Parallel) ? l1.parallelStream()
+                    : (type == ParallelType.Sequential) ? l1.stream().sequential() : l1.stream();
+            Stream<Employee> stream22 = (type == ParallelType.Parallel) ? l2.parallelStream()
+                    : (type == ParallelType.Sequential) ? l2.stream().sequential() : l2.stream();
+            List<Employee> expectedList = Streams.concat(stream12, stream22).filter(p).collect(Collectors.<Employee>toList());
+            List<Employee> testList = result1.stream().collect(Collectors.<Employee>toList());
+
+            Collections.sort(testList, rule.getComparator());
+            Collections.sort(expectedList, rule.getComparator());
+            for (int i = 0; i < testList.size(); i ++) {
+                assertEquals(rule.getValue(testList.get(i)), rule.getValue(expectedList.get(i)));
+            }
+            Collection<Employee> emptyList = hasIni ? LambdaUtilities.create(typeObject, initSize) : LambdaUtilities
+                    .create(typeObject);
+            Stream<Employee> stream3 = (type == ParallelType.Parallel) ? emptyList.parallelStream()
+                    : (type == ParallelType.Sequential) ? emptyList.stream().sequential() : emptyList.stream();
+
+            List<Employee> result3 = Streams.concat(l1.stream(), stream3).collect(Collectors.<Employee>toList());
+            List<Employee> list1 = new ArrayList<>(l1);
+            Collections.sort(list1, rule.getComparator());
+            Collections.sort(result3, rule.getComparator());
+            assertEquals(list1, result3);
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testFilter() throws Exception {
+        Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+        while (iter.hasNext()) {
+            ParallelType type = iter.next();
+            // Create predicate with random limit and random up/down size
+            Collection<Employee> l = generateData(DATA_SIZE);
+            Stream<Employee> stream = (type == ParallelType.Parallel) ? l.parallelStream()
+                    : ((type == ParallelType.Sequential) ? l.stream().sequential() : l.stream());
+            stream = l.stream();
+            Employee.Rule rule = Employee.Rule.values()[rand.nextInt(Employee.Rule.values().length)];
+            Employee limit1 = generateData();
+            limit1.salary = rand.nextFloat() * (Employee.MAX_SALARY * 2);
+            limit1.age = rand.nextInt(Employee.MAX_AGE * 2);
+            boolean isUP1 = rand.nextBoolean();
+            Predicate<Employee> p1 = LambdaUtilities.randomGenericPredicate(isUP1, limit1, rule.getComparator());
+
+            // Filter the data, check if it works as expected.
+            Collection<Employee> result1 = stream.filter(p1).collect(Collectors.toCollection(LinkedList<Employee>::new));
+            assertTrue(verifyMatch(result1, limit1, isUP1, true, rule));
+
+            // filter on parallel stream can cause IllegalStateException
+            stream = (type == ParallelType.Parallel) ? l.parallelStream() : ((type == ParallelType.Sequential) ? l
+                    .stream().sequential() : l.stream());
+            result1.clear();
+            result1 = stream.filter(p1).filter(Predicates.alwaysTrue()).collect(Collectors.toCollection(LinkedList<Employee>::new));
+            assertTrue(verifyMatch(result1, limit1, isUP1, true, rule));
+
+            // filter with Predicates.alwaysFlase() will get nothing
+            stream = (type == ParallelType.Parallel) ? l.parallelStream() : ((type == ParallelType.Sequential) ? l
+                    .stream().sequential() : l.stream());
+            result1.clear();
+
+            result1 = stream.filter(p1).filter(Predicates.alwaysFalse()).collect(Collectors.toCollection(LinkedList<Employee>::new));
+            assertTrue(result1.isEmpty());
+
+            Employee limit2 = generateData();
+            limit2.salary = rand.nextFloat() * (Employee.MAX_SALARY * 2);
+            limit2.age = rand.nextInt(Employee.MAX_AGE * 2);
+            boolean isUP2 = rand.nextBoolean();
+            Predicate<Employee> p2 = LambdaUtilities.randomGenericPredicate(isUP2, limit2, rule.getComparator());
+
+            Employee limit3 = generateData();
+            limit3.salary = rand.nextFloat() * (Employee.MAX_SALARY * 2);
+            limit3.age = rand.nextInt(Employee.MAX_AGE * 2);
+            boolean isUP3 = rand.nextBoolean();
+            Predicate<Employee> p3 = LambdaUtilities.randomGenericPredicate(isUP3, limit3, rule.getComparator());
+
+            stream = (type == ParallelType.Parallel) ? l.parallelStream() : ((type == ParallelType.Sequential) ? l
+                    .stream().sequential() : l.stream());
+            List<Employee> result2 = stream.filter(p1).filter(p2).collect(Collectors.<Employee>toList());
+            stream = (type == ParallelType.Parallel) ? l.parallelStream() : ((type == ParallelType.Sequential) ? l
+                    .stream().sequential() : l.stream());
+             List<Employee> result3 = stream.filter(Predicates.and(p1, p2)).collect(Collectors.<Employee>toList());
+            Collections.sort(result2, rule.getComparator());
+            Collections.sort(result3, rule.getComparator());
+            assertEquals(result2, result3);
+            result2.clear();
+            result3.clear();
+
+            stream = (type == ParallelType.Parallel) ? l.parallelStream() : ((type == ParallelType.Sequential) ? l
+                    .stream().sequential() : l.stream());
+            result2 = stream.filter(Predicates.and(p1, p2)).collect(Collectors.<Employee>toList());
+            stream = (type == ParallelType.Parallel) ? l.parallelStream() : ((type == ParallelType.Sequential) ? l
+                    .stream().sequential() : l.stream());
+            result3 = stream.filter(Predicates.or(p1, p2)).collect(Collectors.<Employee>toList());
+            result2.addAll(result3);
+            result3.clear();
+            stream = (type == ParallelType.Parallel) ? l.parallelStream() : ((type == ParallelType.Sequential) ? l
+                    .stream().sequential() : l.stream());
+            Stream<Employee> stream2 = (type == ParallelType.Parallel) ? l.parallelStream()
+                    : ((type == ParallelType.Sequential) ? l.stream().sequential() : l.stream());
+            result3 = Streams.concat(stream.filter(p1), stream2.filter(p2)).collect(Collectors.<Employee>toList());
+            Collections.sort(result2, rule.getComparator());
+            Collections.sort(result3, rule.getComparator());
+            assertEquals(result2, result3);
+
+            @SuppressWarnings("cast")
+            Collection<Employee> emptyList = hasIni ? (Collection<Employee>) LambdaUtilities.create(typeObject,
+                    initSize) : (Collection<Employee>) LambdaUtilities.create(typeObject);
+            Stream<Employee> stream3 = (type == ParallelType.Parallel) ? emptyList.parallelStream()
+                    : (type == ParallelType.Sequential) ? emptyList.stream().sequential() : emptyList.stream();
+            assertFalse(stream3.filter(p1).iterator().hasNext());
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testFind() throws Exception {
+        Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+        while (iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Employee> c = generateData(DATA_SIZE);
+            Stream<Employee> stream1 = (type == ParallelType.Parallel) ? c.parallelStream()
+                    : (type == ParallelType.Sequential) ? c.stream().sequential() : c.stream();
+            Stream<Employee> stream2 = (type == ParallelType.Parallel) ? c.parallelStream()
+                    : (type == ParallelType.Sequential) ? c.stream().sequential() : c.stream();
+            java.util.Optional<Employee> opAny = stream1.findAny();
+            java.util.Optional<Employee> opFirst = stream2.findFirst();
+            assertTrue(opAny.isPresent());
+            assertTrue(opFirst.isPresent());
+            if (!stream1.isParallel())
+                assertEquals(opAny, opFirst);
+
+            @SuppressWarnings("cast")
+            Collection<Employee> emptyCol = hasIni ? (Collection<Employee>) LambdaUtilities
+                    .create(typeObject, initSize) : (Collection<Employee>) LambdaUtilities.create(typeObject);
+            Stream<Employee> emptyStream1 = (type == ParallelType.Parallel) ? emptyCol.parallelStream()
+                    : (type == ParallelType.Sequential) ? emptyCol.stream().sequential() : emptyCol.stream();
+            java.util.Optional<Employee> emptyAny = emptyStream1.findAny();
+            assertFalse(emptyAny.isPresent());
+            Stream<Employee> emptyStream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream()
+                    : (type == ParallelType.Sequential) ? emptyCol.stream().sequential() : emptyCol.stream();
+            java.util.Optional<Employee> emptyFirsty = emptyStream2.findFirst();
+            assertFalse(emptyFirsty.isPresent());
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testForEach() throws Exception {
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Employee> c =  generateData(DATA_SIZE);
+            Stream<Employee> stream = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+            stream.forEach(t -> { assertTrue(c.contains(t)); });
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testLimit() throws Exception {
+        Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+        while (iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Employee> col = generateData( 10);
+            int limit = rand.nextInt(10 * 2);
+           Employee.Rule rule = Employee.Rule.values()[rand.nextInt(Employee.Rule.values().length)];
+            Stream<Employee> stream1 = (type == ParallelType.Parallel) ? col.parallelStream()
+                    : (type == ParallelType.Sequential) ? col.stream().sequential() : col.stream();
+            List<Employee> result1 = stream1.explode(genEmployeeFlatBiConsumer(2, rule)).collect(Collectors.<Employee>toList());
+
+            Stream<Employee> stream2 = (type == ParallelType.Parallel) ? col.parallelStream()
+                    : (type == ParallelType.Sequential) ? col.stream().sequential() : col.stream();
+            List<Employee> result2 = stream2.explode(genEmployeeFlatBiConsumer(2, rule)).limit(limit)
+                    .collect(Collectors.<Employee>toList());
+
+            if (col instanceof Set) {
+                assertTrue(result2.size() <= (limit < result1.size() ? limit : result1.size()));
+            }else {
+               assertEquals(result2.size(), (limit < result1.size() ? limit : result1.size()));
+            }
+        }
+    }
+
+    @Test
+    @SuppressWarnings({"unchecked","rawtypes"})
+    public void testMax() throws Exception {
+        Employee.Rule rule = Employee.Rule.values()[rand.nextInt(Employee.Rule.values().length)];
+        Comparator<Employee> c1 = rule.getComparator();
+
+        for (Comparator<Employee> c : new Comparator[]{c1, c1.reverseOrder()}) {
+            Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+            while (iter.hasNext()) {
+
+                ParallelType type = iter.next();
+                Collection<Employee> col = generateData(DATA_SIZE);
+                Stream<Employee> stream1 = (type == ParallelType.Parallel) ? col.parallelStream()
+                        : (type == ParallelType.Sequential) ? col.stream().sequential() : col.stream();
+                java.util.Optional<Employee> optional = stream1.max(c);
+                assertTrue(optional.isPresent());
+                assertEquals(rule.getValue(optional.get()), rule.getValue(getMax1(col, c)));
+                assertEquals(rule.getValue(optional.get()), rule.getValue(getMax2(col, c)));
+                assertEquals(rule.getValue(optional.get()), rule.getValue(getMax3(col, c)));
+
+                @SuppressWarnings("cast")
+                Collection<Employee> emptyCol = hasIni ? (Collection<Employee>) LambdaUtilities
+                        .create(typeObject, initSize) : (Collection<Employee>) LambdaUtilities.create(typeObject);
+                Stream<Employee> emptyStream = (type == ParallelType.Parallel) ? emptyCol.parallelStream()
+                        : (type == ParallelType.Sequential) ? emptyCol.stream().sequential() : emptyCol.stream();
+                assertFalse(emptyStream.max(c).isPresent());
+            }
+        }
+    }
+
+    @Test
+    @SuppressWarnings({"unchecked","rawtypes"})
+    public void testMin() throws Exception {
+        Employee.Rule rule = Employee.Rule.values()[rand.nextInt(Employee.Rule.values().length)];
+        Comparator<Employee> c1 = rule.getComparator();
+
+        for (Comparator<Employee> c : new Comparator[]{c1, c1.reverseOrder()}) {
+            Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+            while (iter.hasNext()) {
+
+                ParallelType type = iter.next();
+                Collection<Employee> col = generateData(DATA_SIZE);
+                Stream<Employee> stream1 = (type == ParallelType.Parallel) ? col.parallelStream()
+                        : (type == ParallelType.Sequential) ? col.stream().sequential() : col.stream();
+                java.util.Optional<Employee> optional = stream1.min(c);
+                assertTrue(optional.isPresent());
+                assertEquals(rule.getValue(optional.get()), rule.getValue(getMin1(col, c)));
+                assertEquals(rule.getValue(optional.get()), rule.getValue(getMin2(col, c)));
+                assertEquals(rule.getValue(optional.get()), rule.getValue(getMin3(col, c)));
+
+                @SuppressWarnings("cast")
+                Collection<Employee> emptyCol = hasIni ? (Collection<Employee>) LambdaUtilities
+                        .create(typeObject, initSize) : (Collection<Employee>) LambdaUtilities.create(typeObject);
+                Stream<Employee> emptyStream = (type == ParallelType.Parallel) ? emptyCol.parallelStream()
+                        : (type == ParallelType.Sequential) ? emptyCol.stream().sequential() : emptyCol.stream();
+                assertFalse(emptyStream.min(c).isPresent());
+            }
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testNoneMatch() throws Exception {
+        Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+        while (iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Employee> c1 = generateData(DATA_SIZE);
+            Employee.Rule rule = Employee.Rule.values()[rand.nextInt(Employee.Rule.values().length)];
+            Employee limit = generateData();
+            limit.salary = rand.nextFloat() * (Employee.MAX_SALARY * 2);
+            limit.age = rand.nextInt(Employee.MAX_AGE * 2);
+            boolean isUP = rand.nextBoolean();
+            Stream<Employee> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream()
+                    : (type == ParallelType.Sequential) ? c1.stream().sequential() : c1.stream();
+            assertEquals(stream1.noneMatch(LambdaUtilities.randomGenericPredicate(isUP, limit, rule.getComparator())),
+                    verifyMatch(c1, limit, !isUP, true, rule));
+
+            // Empty stream's noneMatch will return true always
+            @SuppressWarnings("cast")
+            Collection<Employee> emptyCol = hasIni ? (Collection<Employee>) LambdaUtilities
+                    .create(typeObject, initSize) : (Collection<Employee>) LambdaUtilities.create(typeObject);
+            Stream<Employee> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream()
+                    : (type == ParallelType.Sequential) ? emptyCol.stream().sequential() : emptyCol.stream();
+            assertTrue(stream2.noneMatch(LambdaUtilities.randomGenericPredicate(isUP, limit, rule.getComparator())));
+        }
+    }
+
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testSubstream() throws Exception {
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        BiFunction<Integer,Integer,Integer> bf = LambdaUtilities.randBetweenIntegerFunction();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Employee> col =  generateData(DATA_SIZE);
+            int skip = rand.nextInt(col.size());
+            //limit has more than 50% chance less than col.size() - skip
+            int limit = rand.nextBoolean() ?
+                    bf.apply(0, col.size() - skip) :
+                    rand.nextInt(Integer.MAX_VALUE);
+            Stream<Employee> stream1 = (type == ParallelType.Parallel) ? col.parallelStream():
+                    (type == ParallelType.Sequential) ? col.stream().sequential() :
+                    col.stream();
+            Iterator<Employee> it = stream1.substream(skip, skip + limit).iterator();
+            verifySlice(col.iterator(), it, skip, limit);
+
+            //limit=0 causes empty stream
+            Stream<Employee> stream2 = (type == ParallelType.Parallel) ? col.parallelStream():
+                    (type == ParallelType.Sequential) ? col.stream().sequential() :
+                    col.stream();
+            assertFalse(stream2.substream(skip, skip).iterator().hasNext());
+
+            //skip exceed collection size cause  empty stream
+            Stream<Employee> stream3 = (type == ParallelType.Parallel) ? col.parallelStream():
+                    (type == ParallelType.Sequential) ? col.stream().sequential() :
+                    col.stream();
+            int skipExceeded = bf.apply(col.size(), Integer.MAX_VALUE);
+            assertFalse(stream3.substream(skipExceeded, skipExceeded + 1).iterator().hasNext());
+
+            @SuppressWarnings("cast")
+            Collection<Employee> emptyCol  = hasIni ?
+                    (Collection<Employee>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Employee>)LambdaUtilities.create(typeObject);
+            Stream<Employee> emptyStream = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                emptyCol.stream();
+            assertFalse(emptyStream.substream(skip, skip + limit).iterator().hasNext());
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testSorted() throws Exception {
+        Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+        while (iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Employee> col = generateData(DATA_SIZE);
+            Employee.Rule rule = Employee.Rule.values()[rand.nextInt(Employee.Rule.values().length)];
+            Comparator<Employee> c = rule.getComparator();
+            Stream<Employee> stream = (type == ParallelType.Parallel) ? col.parallelStream()
+                    : (type == ParallelType.Sequential) ? col.stream().sequential() : col.stream();
+            List<Employee> reversed = stream.sorted(c.reverseOrder()).collect(Collectors.<Employee>toList());
+            // The reason conver l to sorted is CopyOnWriteArrayList doesn't
+            // support
+            // sort, we use ArrayList sort data instead
+            List<Employee> sorted = new ArrayList<>(col);
+            Collections.sort(sorted, c);
+
+            // SortedSet instance's stream can't be reordered
+            if (!(col instanceof SortedSet)) {
+                Collections.reverse(sorted);
+                for (int i = 0; i < sorted.size(); i ++) {
+                        assertEquals(rule.getValue(sorted.get(i)), rule.getValue(reversed.get(i)));
+                    }
+            }
+
+            @SuppressWarnings("cast")
+            Collection<Employee> emptyCol = hasIni ?
+                    (Collection<Employee>) LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Employee>) LambdaUtilities.create(typeObject);
+            Stream<Employee> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream()
+                    : (type == ParallelType.Sequential) ? emptyCol.stream().sequential() : emptyCol.stream();
+            assertFalse(stream2.sorted(Collections.reverseOrder()).iterator().hasNext());
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testToArray() throws Exception {
+        Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+        while (iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Employee> c1 = generateData(DATA_SIZE);
+            Stream<Employee> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream()
+                    : (type == ParallelType.Sequential) ? c1.stream().sequential() : c1.stream();
+            Object[] arr1 = stream1.toArray();
+            Object[] arr2 = c1.toArray();
+            assert (arr1.length == arr2.length);
+            for (int index = 0; index < arr1.length; index++) {
+                assertEquals(arr1[index], arr2[index]);
+            }
+
+            @SuppressWarnings("cast")
+            Collection<Employee> emptyCol = hasIni ?
+                    (Collection<Employee>) LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Employee>) LambdaUtilities.create(typeObject);
+            Stream<Employee> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream()
+                    : (type == ParallelType.Sequential) ? emptyCol.stream().sequential() : emptyCol.stream();
+            assertEquals(stream2.toArray().length, 0);
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testUniqueElements() throws Exception {
+        Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+        while (iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Employee> c1 = generateData(DATA_SIZE);
+            Set<Employee> set1 = new HashSet<>(c1);
+            Employee.Rule rule = Employee.Rule.values()[rand.nextInt(Employee.Rule.values().length)];
+            Stream<Employee> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream()
+                    : (type == ParallelType.Sequential) ? c1.stream().sequential() : c1.stream();
+            List<Employee> list2 = stream1.explode(genEmployeeFlatBiConsumer(4, rule)).distinct().collect(Collectors.<Employee>toList());
+            assertEquals(set1.size(), list2.size());
+            assertTrue(set1.containsAll(list2));
+        }
+    }
+
+    private Collection<Employee> generateData(int size) throws Exception {
+        Collection<Employee> col = hasIni ? LambdaUtilities.create(typeObject, initSize) :
+                LambdaUtilities.create(typeObject);
+        for (int i = 0; i < size; i++) {
+            col.add(generateData());
+        }
+        return col;
+    }
+
+    private Employee generateData() throws Exception {
+        Employee element = new Employee();
+        element.id = StringUtilities.randomString(Employee.MAX_ID, Employee.MIN_ID);
+        element.age = Employee.MIN_AGE + rand.nextInt(Employee.MAX_AGE - Employee.MIN_AGE);
+        element.male = rand.nextBoolean();
+        element.salary = Employee.MIN_SALARY + rand.nextFloat() * (Employee.MAX_SALARY - Employee.MIN_SALARY);
+        int idx = rand.nextInt(Employee.Title.values().length);
+        element.title = Employee.Title.values()[idx];
+        return element;
+    }
+
+    private boolean verifyMatch(Collection<Employee> c, Employee limit, boolean isUP, boolean all, Employee.Rule rule) {
+        Comparator<Employee> cmp = rule.getComparator();
+        Iterator<Employee> it = c.iterator();
+        while (it.hasNext()) {
+            Employee current = it.next();
+            if (isUP) {
+                if (all) {
+                    if (cmp.compare(current, limit) < 0)
+                        return false;
+                } else {
+                    if (cmp.compare(current, limit) >= 0)
+                        return true;
+                }
+            } else {
+                if (all) {
+                    if (cmp.compare(current, limit) >= 0)
+                        return false;
+                } else {
+                    if (cmp.compare(current, limit) < 0) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return all;
+    }
+
+    private void verifyGroupBy(Map<?, Collection<Employee>> result, boolean isFirst, Employee.Rule rule) {
+        Iterator<?> keyiter = result.keySet().iterator();
+        while (keyiter.hasNext()) {
+            Object obj = keyiter.next();
+            switch (rule) {
+            case AGE:
+                Integer key0 = (Integer) obj;
+                assertTrue(key0 < 10 && key0 >= 0);
+                Iterator<Employee> valueiter0 = result.get(key0).iterator();
+                while (valueiter0.hasNext()) {
+                    Employee i = valueiter0.next();
+                    if (isFirst)
+                        assertTrue(Integer.valueOf(Integer.toString(i.age).substring(0, 1)) == key0);
+                    else {
+                        String v = Integer.toString(i.age);
+                        int l = v.length();
+                        assertTrue(Integer.valueOf(v.substring(l - 1, l)) == key0);
+                    }
+                }
+                break;
+            case SALARY:
+                Integer key1 = (Integer) obj;
+                assertTrue(key1 < 10 && key1 >= 0);
+                Iterator<Employee> valueiter1 = result.get(key1).iterator();
+                while (valueiter1.hasNext()) {
+                    Employee i = valueiter1.next();
+                    if (isFirst)
+                        assertTrue(Integer.valueOf(Float.toString(i.salary).substring(0, 1)) == key1);
+                    else {
+                        String v = Float.toString(i.salary);
+                        int len = v.length();
+                        assertTrue(Integer.valueOf(v.substring(len - 1, len)) == key1);
+                    }
+                }
+                break;
+            case MALE:
+                Boolean key2 = (Boolean) obj;
+                Iterator<Employee> valueiter2 = result.get(key2).iterator();
+                while (valueiter2.hasNext()) {
+                    Employee i = valueiter2.next();
+                    assertTrue(Boolean.valueOf(i.male) == key2);
+                }
+                break;
+            case TITLE:
+                Employee.Title key3 = (Employee.Title) obj;
+                Iterator<Employee> valueiter3 = result.get(key3).iterator();
+                while (valueiter3.hasNext()) {
+                    Employee i = valueiter3.next();
+                    assertTrue(i.title == key3);
+                }
+                break;
+            case ID:
+            default:
+                LambdaUtilities.CharType key4 = (LambdaUtilities.CharType) obj;
+                Iterator<Employee> valueiter4 = result.get(key4).iterator();
+                while (valueiter4.hasNext()) {
+                    Employee i = valueiter4.next();
+                    Character c = null;
+                    if (isFirst)
+                        c = Character.valueOf(i.id.charAt(0));
+                    else
+                        c = Character.valueOf(i.id.charAt(i.id.length() - 1));
+                    LambdaUtilities.CharType t = Character.isAlphabetic(c) ? (Character.isUpperCase(c) ? LambdaUtilities.CharType.UPPERCASE
+                            : LambdaUtilities.CharType.LOWERCASE)
+                            : (Character.isDigit(c) ? LambdaUtilities.CharType.DIGIT : LambdaUtilities.CharType.SPECIAL);
+                    assertTrue(t == key4);
+                }
+                break;
+            }
+        }
+    }
+
+    private void verifyMultiFunction(Collection<Employee> orig, List<Employee> result,
+            int selected, int unit, Employee.Rule rule) throws Exception {
+        Comparator<Employee> cmp = rule.getComparator();
+        switch (selected) {
+        case 0:
+            assertEquals(result.size(), 0);
+            break;
+        case 1:
+            List<Employee> l1 = new ArrayList<>(orig);
+            Collections.sort(l1, cmp);
+            Collections.sort(result, cmp);
+            assertEquals(l1, result);
+            break;
+        case 2:
+            List<Employee> l2 = new ArrayList<>();
+            Iterator<Employee> it2 = orig.iterator();
+            switch (rule) {
+            case AGE:
+                while (it2.hasNext()) {
+                    Employee cur = it2.next();
+                    for (int i = 0; i < cur.age; i ++) {
+                        Employee employee = new Employee();
+                        employee.age = cur.age * (cur.age - 1) / 2 + i;
+                        l2.add(employee);
+                    }
+                }
+                break;
+            case SALARY:
+                l2 = new ArrayList<>();
+                it2 = orig.iterator();
+                while (it2.hasNext()) {
+                    Employee cur = it2.next();
+                    for (int i = 0; i < cur.salary; i ++) {
+                        Employee employee = new Employee();
+                        employee.salary = cur.salary * (cur.salary - 1) / 2 + i;
+                        l2.add(employee);
+                    }
+                }
+                break;
+            case ID:
+                l2 = new ArrayList<>();
+                it2 = orig.iterator();
+                while (it2.hasNext()) {
+                    Employee cur = it2.next();
+                    int step = cur.id.length() / unit + unit - 1;
+                    for (int i = 0; i < cur.id.length(); i += step) {
+                        Employee employee = new Employee();
+                        employee.id = new String(cur.id.substring(i, i + step >= cur.id.length() ?  cur.id.length() - 1 : i + step));
+                        l2.add(employee);
+                    }
+                }
+                break;
+            case MALE:
+                l2 = new ArrayList<>();
+                it2 = orig.iterator();
+                while (it2.hasNext()) {
+                    Employee cur = it2.next();
+                    Employee employee = new Employee();
+                    employee.male = !cur.male;
+                    l2.add(employee);
+                }
+                break;
+            case TITLE:
+                l2 = new ArrayList<>();
+                it2 = orig.iterator();
+                while (it2.hasNext()) {
+                    Employee cur = it2.next();
+                    for (int i = 0; i < cur.title.ordinal(); i ++) {
+                        Employee employee = new Employee();
+                        employee.title = Employee.Title.values()[i];
+                        l2.add(employee);
+                    }
+                }
+                break;
+            }
+            Collections.sort(l2, cmp);
+            Collections.sort(result, cmp);
+            assertEquals(l2, result);
+            break;
+        case 3:
+            List<Employee> l3 = new ArrayList<>();
+            Iterator<Employee> it3 = orig.iterator();
+            while (it3.hasNext()) {
+                Employee current = it3.next();
+                for (int i = 0; i < unit; i++)
+                    l3.add(current);
+            }
+            Collections.sort(l3, cmp);
+            Collections.sort(result, cmp);
+            assertEquals(l3, result);
+            break;
+        default:
+            break;
+        }
+    }
+
+    private Employee getMax1(Collection<Employee> col, Comparator<Employee> c) {
+        assert (!col.isEmpty());
+        Iterator<Employee> it = col.iterator();
+        Employee max = it.next();
+        while (it.hasNext()) {
+            Employee next = it.next();
+            if (c.compare(max, next) < 0)
+                max = next;
+        }
+        return max;
+    }
+
+    private Employee getMax2(Collection<Employee> col, Comparator<Employee> c) {
+        assert (!col.isEmpty());
+        Employee any = col.iterator().next();
+        java.util.Optional<Employee> max = col.stream().reduce(LambdaUtilities.maxGenericBinaryOperator(c));
+        assert (max.isPresent());
+        return max.get();
+    }
+
+    private Employee getMax3(Collection<Employee> col, Comparator<Employee> c) {
+        assert (!col.isEmpty());
+        Employee any = col.iterator().next();
+        Employee max = col.stream().reduce(any, LambdaUtilities.maxGenericFunction(c),
+                LambdaUtilities.maxGenericBinaryOperator(c));
+        return max;
+    }
+
+    private Employee getMax4(Collection<Employee> col, Comparator<Employee> c) {
+        assert (!col.isEmpty());
+        AtomicReference<Employee> max = col.stream().collect(LambdaUtilities.atomicGenericSupplier(new Employee()),
+                LambdaUtilities.maxGenericBiConsumer(c), LambdaUtilities.maxAtomicGenericBiConsumer(c));
+        return max.get();
+    }
+
+    /*
+     * c could be reversed order, we can't use MAX_VALUE or MIN_VALUE but we can
+     * use 1st element to compare with.
+     */
+    private Employee getMin1(Collection<Employee> col, Comparator<Employee> c) {
+        assert (!col.isEmpty());
+        Iterator<Employee> it = col.iterator();
+        Employee min = it.next();
+        while (it.hasNext()) {
+            Employee next = it.next();
+            if (c.compare(min, next) > 0)
+                min = next;
+        }
+        return min;
+    }
+
+    private Employee getMin2(Collection<Employee> col, Comparator<Employee> c) {
+        assert (!col.isEmpty());
+        Employee any = col.iterator().next();
+        java.util.Optional<Employee> min = col.stream().reduce(LambdaUtilities.minGenericBinaryOperator(c));
+        assert (min.isPresent());
+        return min.get();
+    }
+
+    private Employee getMin3(Collection<Employee> col, Comparator<Employee> c) {
+        assert (!col.isEmpty());
+        Employee any = col.iterator().next();
+        Employee min = col.stream().reduce(any, LambdaUtilities.minGenericFunction(c),
+                LambdaUtilities.minGenericBinaryOperator(c));
+        return min;
+    }
+
+    private Employee getMin4(Collection<Employee> col, Comparator<Employee> c) {
+        assert (!col.isEmpty());
+        AtomicReference<Employee> min = col.stream().collect(LambdaUtilities.atomicGenericSupplier(new Employee()),
+                LambdaUtilities.minGenericBiConsumer(c), LambdaUtilities.minAtomicGenericBiConsumer(c));
+        return min.get();
+    }
+
+    private void verifySlice(Iterator<Employee> itOrg, Iterator<Employee> itSliced, int skip, int limit) {
+        int pos = 0;
+        while (itOrg.hasNext() && pos++ < skip)
+            itOrg.next();
+
+        while (itOrg.hasNext() && pos++ < limit)
+            assertEquals(itOrg.next(), itSliced.next());
+
+    }
+
+    public static BiConsumer<Stream.Downstream<Employee>, Employee>
+            genEmployeeFlatBiConsumer(int selected, Employee.Rule rule) {
+        switch (selected) {
+            case 0:
+                //Generate a empty collection
+                return ( s, e ) -> { };
+            case 1:
+                return ( s, e ) -> { s.send(e); };
+            case 2:
+                switch (rule) {
+                case AGE:
+                    return ( s, e ) -> {
+                        for (int i = 0; i < e.age; i+= e.age / 10) {
+                            Employee employee = e.clone();
+                            employee.id = e.id;
+                            employee.age = e.age * (e.age - 1) / 2 + i;
+                            s.send(employee);
+                        }
+                    };
+                case SALARY:
+                    return ( s, e ) -> {
+                        for (int i = 0; i < (int)e.salary; i+= (int)e.salary / 10) {
+                            Employee employee = e.clone();
+                            employee.id = e.id;
+                            employee.salary = e.salary * (e.salary - 1) / 2 + i;
+                            s.send(employee);
+                        }
+                    };
+                case MALE:
+                    return (s, e) -> {
+                          Employee employee = e.clone();
+                          employee.male = !e.male;
+                          employee.id = e.id;
+                          s.send(employee);
+                    };
+                case TITLE:
+                    return (s, e) -> {
+                        for (int i = 0; i < e.title.ordinal(); i ++) {
+                            Employee employee = e.clone();
+                            employee.title = Employee.Title.values()[i];
+                            employee.id = e.id;
+                            s.send(employee);
+                        }
+                    };
+                case ID:
+                default:
+                    return (s, e) -> {
+                        for (int i = 0; i < e.id.length(); i += 2) {
+                            Employee employee = e.clone();
+                            employee.id = e.id;
+                            s.send(employee);
+                        }
+                    };
+                }
+            case 3:
+            default:
+                return ( s, e ) -> {
+                    for (int i = 0; i < 10; i++) {
+                        s.send(e);
+                    }
+                };
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/stream/Stream/IntStreamTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,801 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Basic test for IntStream
+ * @library ../..
+ * @(#) IntStreamTest.java
+ * @author Tristan Yan
+ * @run testng IntStreamTest
+ */
+
+
+import java.util.*;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.BiFunction;
+import java.util.function.IntPredicate;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+import java.util.stream.Streams;
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+public class IntStreamTest {
+    protected final static int ARRAY_SIZE = 1 << 12;
+
+    protected final static int END = 1 << 6;
+
+    static enum ParallelType { Parallel, Sequential, Default};
+
+    protected final static Random rand = new Random(System.currentTimeMillis());
+
+    protected int[] generateData(int size) {
+        return rand.ints().limit(size).toArray();
+    }
+
+    protected int[] generateShortData(int size)
+            throws Exception{
+        int[] array = generateData(size);
+        for(int i = 0; i < size; i++) {
+            array[i] = array[i] & 0xffff;
+        }
+        return array;
+    }
+
+    private boolean verifyMatch(int[] array, int limit, boolean isUP,
+            boolean all, int startIndex, int endIndex) {
+        assert(startIndex >= 0 && endIndex <= array.length
+                && startIndex <= endIndex);
+        for(int index = startIndex ; index < endIndex; index++) {
+            int current = array[index];
+            if(isUP) {
+                if(all) {
+                    if(current < limit) return false;
+                } else {
+                    if(current >= limit) return true;
+                }
+            } else {
+                if(all) {
+                    if(current >= limit) return false;
+                } else {
+                    if(current < limit) return true;
+                }
+            }
+        }
+        return all;
+    }
+
+
+    private boolean verifyMatch(int[] array, int limit1, boolean isUP1,
+             int limit2, boolean isUP2, boolean and, boolean all) {
+        IntPredicate p1 = LambdaUtilities.randomIntPredicate(isUP1, limit1);
+        IntPredicate p2 = LambdaUtilities.randomIntPredicate(isUP2, limit2);
+        for(int index = 0 ; index < array.length; index++) {
+            int current = array[index];
+            if(and) {
+                if(all) {
+                    if(!p1.test(current) || !p2.test(current))
+                        return false;
+                } else {
+                    if(p1.test(current) && p2.test(current))
+                        return true;
+                }
+            } else {
+                if(all) {
+                    if(!p1.test(current) && !p2.test(current))
+                        return false;
+                } else {
+                    if(p1.test(current) || p2.test(current))
+                        return true;
+                }
+            }
+        }
+        return all;
+    }
+
+    @Test
+    public void testAllMatch() throws Exception{
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            int[] array = generateData(ARRAY_SIZE);
+            int limit = rand.nextInt();
+            boolean isUP = rand.nextBoolean();
+            IntStream stream1 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            assertEquals(stream1.allMatch(LambdaUtilities.randomIntPredicate(isUP, limit)),
+                    verifyMatch(array, limit, isUP, true , 0, array.length));
+
+            int startIndex = rand.nextInt(array.length);
+            int endIndex = startIndex + rand.nextInt(array.length - startIndex + 1);
+            IntStream stream2 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array, startIndex, endIndex)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array, startIndex, endIndex).sequential() :
+                    Arrays.stream(array, startIndex, endIndex);
+            assertEquals(stream2.allMatch(LambdaUtilities.randomIntPredicate(isUP, limit)),
+                    verifyMatch(array, limit, isUP, true , startIndex, endIndex));
+        }
+    }
+
+    @Test
+    public void testAnyMatch() throws Exception {
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            int[] array = generateData(ARRAY_SIZE);
+            int limit = rand.nextInt();
+            boolean isUP = rand.nextBoolean();
+            IntStream stream1 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            assertEquals(stream1.anyMatch(LambdaUtilities.randomIntPredicate(isUP, limit)),
+                    verifyMatch(array, limit, isUP, false , 0, array.length));
+
+            int startIndex = rand.nextInt(array.length);
+            int endIndex = startIndex + rand.nextInt(array.length - startIndex + 1);
+            IntStream stream2 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array, startIndex, endIndex)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array, startIndex, endIndex).sequential() :
+                    Arrays.stream(array, startIndex, endIndex);
+            assertEquals(stream2.anyMatch(LambdaUtilities.randomIntPredicate(isUP, limit)),
+                    verifyMatch(array, limit, isUP, false , startIndex, endIndex));
+        }
+    }
+
+    @Test
+    public void testAveargeAndSum() throws Exception {
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            int[] array = generateData(ARRAY_SIZE);
+            IntStream sumStream1 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            IntStream avgStream1 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            long total1 = 0;
+            for(int index = 0; index < array.length; index++) {
+                total1 += array[index];
+            }
+            assertEquals(avgStream1.average().getAsDouble(), (double)total1 / array.length);
+            assertEquals(sumStream1.sum(), total1);
+
+            int startIndex = rand.nextInt(array.length);
+            int endIndex = startIndex + rand.nextInt(array.length - startIndex + 1);
+            IntStream sumStream2 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array, startIndex, endIndex)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array, startIndex, endIndex).sequential() :
+                    Arrays.stream(array, startIndex, endIndex);
+            IntStream avgStream2 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array, startIndex, endIndex)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array, startIndex, endIndex).sequential() :
+                    Arrays.stream(array, startIndex, endIndex);
+            if(endIndex == startIndex){
+               assertEquals(avgStream2.average(), OptionalDouble.empty());
+               assertEquals(sumStream2.sum(), 0);
+            } else {
+                long total2 = 0;
+                for(int index = startIndex; index < endIndex; index++) {
+                    total2 += array[index];
+                }
+                assertEquals(avgStream2.average().getAsDouble(), (double)total2 / (endIndex - startIndex));
+                assertEquals(sumStream2.sum(), total2);
+            }
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testBoxed() throws Exception {
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            int[] array = generateData(ARRAY_SIZE);
+            IntStream stream1 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            Object[] boxedArr1 = stream1.boxed().toArray();
+            assertTrue(boxedArr1.length == array.length);
+            for(int index = 0; index < array.length; index++)
+                assertTrue((Integer)(boxedArr1[index]) == array[index]);
+
+            int startIndex = rand.nextInt(array.length);
+            int endIndex = startIndex + rand.nextInt(array.length - startIndex + 1);
+            IntStream stream2 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array, startIndex, endIndex)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array, startIndex, endIndex).sequential() :
+                    Arrays.stream(array, startIndex, endIndex);
+            Object[] boxedArr2 = stream2.boxed().toArray();
+            assertEquals(boxedArr2.length, endIndex - startIndex);
+            for(int index = startIndex; index < endIndex; index++)
+                assertEquals((Integer)boxedArr2[index - startIndex], Integer.valueOf(array[index]));
+        }
+    }
+
+    @Test
+    public void testFilter() throws Exception{
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            int[] array = generateData(ARRAY_SIZE);
+            IntStream stream1 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            int limit1 = rand.nextInt();
+            boolean isUP1 = rand.nextBoolean();
+            IntPredicate p1 = LambdaUtilities.randomIntPredicate(isUP1, limit1);
+            int[] filtered =stream1.filter(p1).toArray();
+            assertTrue(verifyMatch(filtered, limit1, isUP1, true , 0, filtered.length));
+
+            stream1 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            int[] filteredNegate =stream1.filter(p1.negate()).toArray();
+            assertTrue(verifyMatch(filteredNegate, limit1, !isUP1, true , 0, filteredNegate.length));
+
+            stream1 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            int limit2 = rand.nextInt();
+            boolean isUP2 = rand.nextBoolean();
+            IntPredicate p2 = LambdaUtilities.randomIntPredicate(isUP2, limit2);
+            assertTrue(verifyMatch(stream1.filter(p1.and(p2)).toArray(), limit1, isUP1,
+                    limit2, isUP2, true, true));
+
+            stream1 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            int limit3 = rand.nextInt();
+            boolean isUP3 = rand.nextBoolean();
+            IntPredicate p3 = LambdaUtilities.randomIntPredicate(isUP3, limit3);
+            assertTrue(verifyMatch(stream1.filter(p1.or(p3)).toArray(), limit1, isUP1,
+                    limit3, isUP3, false, true));
+        }
+    }
+
+    @Test
+    public void testFind() throws Exception{
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            int[] array = generateData(ARRAY_SIZE);
+            IntStream stream1 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            IntStream stream2 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            OptionalInt opAny = stream1.findAny();
+            OptionalInt opFirst = stream2.findFirst();
+            assertTrue(opAny.isPresent());
+            assertTrue(opFirst.isPresent());
+            if(!stream1.isParallel())
+                assertEquals(opAny, opFirst);
+
+            int[] emptyArray = new int[0];
+            IntStream emptyStream1 = (p == ParallelType.Parallel) ? Arrays.parallelStream(emptyArray)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(emptyArray).sequential() :
+                    Arrays.stream(emptyArray);
+            IntStream emptyStream2 = (p == ParallelType.Parallel) ? Arrays.parallelStream(emptyArray)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(emptyArray).sequential() :
+                    Arrays.stream(emptyArray);
+            assertFalse(emptyStream1.findAny().isPresent());
+            assertFalse(emptyStream2.findFirst().isPresent());
+        }
+    }
+
+    @Test
+    public void testForEach() throws Exception {
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            final int[] array = generateData(ARRAY_SIZE);
+            IntStream stream = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            Arrays.parallelSort(array);
+            stream.forEach(t -> { assertTrue(Arrays.binarySearch(array, t) >= 0); });
+
+            int[] emptyArray = new int[0];
+            IntStream emptyStream = (p == ParallelType.Parallel) ? Arrays.parallelStream(emptyArray)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(emptyArray).sequential() :
+                    Arrays.stream(emptyArray);
+            ArrayList<Integer> touch = new ArrayList<>();
+            emptyStream.forEach(t -> { touch.add(t); });
+            assertTrue(touch.isEmpty());
+        }
+    }
+
+    @Test
+    public void testLimit() throws Exception {
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            //mapMulti could cause OOM if we put random values into array
+            final int[] array = new int[ARRAY_SIZE];
+            for(int i = 0; i < ARRAY_SIZE; i++) {
+                array[i] = i + 1;
+            }
+            IntStream stream1 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            IntStream stream2 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            int limit = rand.nextInt(ARRAY_SIZE * (ARRAY_SIZE - 1));
+            int[] flatArr = stream1.explode(LambdaUtilities.genFlatIntConsumer(2)).toArray();
+            int[] result= stream2.explode(LambdaUtilities.genFlatIntConsumer(2)).limit(limit).toArray();
+            if(limit > flatArr.length)
+                assertEquals(flatArr.length,result.length);
+            else {
+                assertEquals(result.length, limit);
+            }
+        }
+    }
+
+    @Test
+    public void testExplode() throws Exception {
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            int[] array = new int[END];
+            for(int i = 0; i < array.length; i++)
+                array[i] = i + 1;
+            IntStream stream = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            int selected = rand.nextInt(5);
+            int[] flatArray = stream.explode(LambdaUtilities.genFlatIntConsumer(selected)).sorted().toArray();
+            verifyMultifunction(array, flatArray, selected);
+        }
+    }
+
+    @Test
+    public void testMap() throws Exception {
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            int[] array = generateData(ARRAY_SIZE);
+            IntStream stream1 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            int randOps = rand.nextInt();
+            int selected = rand.nextInt(5);
+            LambdaUtilities.IntOp op = LambdaUtilities.IntOp.values()[selected];
+            int[] opArray1 = stream1.map(LambdaUtilities.opIntUnaryOperator(op, randOps)).toArray();
+            verifyAfterOps(array, opArray1, op, randOps);
+            IntStream stream2 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            IntStream stream3 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            Object[] objArray1 = stream2.map(LambdaUtilities.opIntUnaryOperator(op, randOps)).boxed().toArray();
+            Object[] objArray2 = stream3.map(LambdaUtilities.opIntFunction(op, randOps)).toArray();
+            assertEquals(objArray1.length, objArray2.length);
+            for(int index = 0; index < objArray1.length; index++) {
+                assertEquals(objArray1[index], objArray2[index]);
+            }
+        }
+    }
+
+    @Test
+    public void testMax() throws Exception {
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            final int[] array = generateData(ARRAY_SIZE);
+            IntStream stream1 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            OptionalInt max = stream1.max();
+            assertEquals(max.getAsInt(), getMax1(array));
+            assertEquals(max.getAsInt(), getMax2(array));
+            assertEquals(max.getAsInt(), getMax3(array));
+
+            IntStream emptyStream = (p == ParallelType.Parallel) ? Arrays.parallelStream(new int[0])
+                    : (p == ParallelType.Sequential) ? Arrays.stream(new int[0]).sequential() :
+                    Arrays.stream(new int[0]);
+            assertFalse(emptyStream.max().isPresent());
+        }
+    }
+
+    @Test
+    public void testMin() throws Exception {
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            final int[] array = generateData(ARRAY_SIZE);
+            IntStream stream1 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            OptionalInt min = stream1.min();
+            assertEquals(min.getAsInt(), getMin1(array));
+            assertEquals(min.getAsInt(), getMin2(array));
+            assertEquals(min.getAsInt(), getMin3(array));
+
+            IntStream emptyStream = (p == ParallelType.Parallel) ? Arrays.parallelStream(new int[0])
+                    : (p == ParallelType.Sequential) ? Arrays.stream(new int[0]).sequential() :
+                    Arrays.stream(new int[0]);
+            //We should consider it as bug, it should throw Exception, will make
+            //sure when all code finalized
+            assertFalse(emptyStream.min().isPresent());
+        }
+    }
+
+    @Test
+    public void testNoneMatch() throws Exception  {
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            final int[] array = generateData(ARRAY_SIZE);
+            int limit = rand.nextInt();
+            boolean isUP = rand.nextBoolean();
+            IntStream stream = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            assertEquals(stream.noneMatch(LambdaUtilities.randomIntPredicate(isUP, limit)),
+                    verifyMatch(array, limit, !isUP, true , 0, array.length));
+
+            IntStream emptyStream = (p == ParallelType.Parallel) ? Arrays.parallelStream(new int[0])
+                    : (p == ParallelType.Sequential) ? Arrays.stream(new int[0]).sequential() :
+                    Arrays.stream(new int[0]);
+            //We should consider it as bug, it should throw Exception, will make
+            //sure when all code finalized
+            assertTrue(emptyStream.noneMatch(LambdaUtilities.randomIntPredicate(isUP, limit)));
+        }
+    }
+
+    @Test
+    public void testSpliterator() throws Exception  {
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            final int[] array = generateData(ARRAY_SIZE);
+            IntStream stream = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            int[] calArr = Streams.intStream(stream.spliterator(), Streams.STREAM_IS_SORTED).toArray();
+            for(int index = 0; index < array.length; index++)
+                assertEquals(array[index], calArr[index]);
+        }
+    }
+
+    @Test
+    public void testReduceWithBase() throws Exception  {
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            if(p == ParallelType.Parallel)
+                continue;
+            final int[] array = generateData(ARRAY_SIZE);
+            int base = rand.nextInt();
+            IntStream streamPlus = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            int oiPlus = streamPlus.reduce(base, LambdaUtilities.addIntBinaryOperator());
+            int total = 0;
+            for(int index = 0; index < array.length; index++)
+                total += array[index];
+            assertEquals(oiPlus, total + base);
+
+            IntStream streamSubtract = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            int oiSubtract = streamSubtract.reduce(base, LambdaUtilities.subIntBinaryOperator());
+            int subTotal = base;
+            for(int index = 0; index < array.length; index++)
+                subTotal -= array[index];
+            assertEquals(oiSubtract, subTotal);
+
+            IntStream emptyStream = (p == ParallelType.Parallel) ? Arrays.parallelStream(new int[0])
+                    : (p == ParallelType.Sequential) ? Arrays.stream(new int[0]).sequential() :
+                    Arrays.stream(new int[0]);
+            int emptyByBase = emptyStream.reduce(base, rand.nextBoolean() ?
+                    LambdaUtilities.addIntBinaryOperator() :
+                    LambdaUtilities.subIntBinaryOperator());
+            assertEquals(emptyByBase, base);
+        }
+    }
+
+    @Test
+    public void testReduceWithoutBase() throws Exception  {
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            final int[] array = generateData(ARRAY_SIZE);
+            IntStream streamPlus = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            OptionalInt oiPlus = streamPlus.reduce(LambdaUtilities.addIntBinaryOperator());
+            assertTrue(oiPlus.isPresent());
+            int total = 0;
+            for(int index = 0; index < array.length; index++)
+                total += array[index];
+            assertTrue(oiPlus.getAsInt() == total);
+
+            //Can't predict Parallel Substract reduce result, give up testing on
+            //parallel substract test
+            if(p == ParallelType.Parallel)
+                continue;
+
+            IntStream streamSubtract = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            OptionalInt oiSubtract = streamSubtract.reduce(LambdaUtilities.subIntBinaryOperator());
+            assertTrue(oiSubtract.isPresent());
+            int subTotal = array[0];
+            for(int index = 1; index < array.length; index++)
+                subTotal -= array[index];
+            assertEquals(oiSubtract.getAsInt(), subTotal);
+
+            IntStream emptyStream = (p == ParallelType.Parallel) ? Arrays.parallelStream(new int[0])
+                    : (p == ParallelType.Sequential) ? Arrays.stream(new int[0]).sequential() :
+                    Arrays.stream(new int[0]);
+            OptionalInt emptyOp = emptyStream.reduce(rand.nextBoolean() ?
+                    LambdaUtilities.addIntBinaryOperator() :
+                    LambdaUtilities.subIntBinaryOperator());
+            assertFalse(emptyOp.isPresent());
+        }
+    }
+
+    @Test
+    public void testSubstream() throws Exception {
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        BiFunction<Integer,Integer,Integer> bf = LambdaUtilities.randBetweenIntegerFunction();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            final int[] array = generateData(ARRAY_SIZE);
+            int skip = rand.nextInt(ARRAY_SIZE);
+            //limit has more than 50% chance less than col.size() - skip
+            int limit = rand.nextBoolean() ?
+                    bf.apply(0, ARRAY_SIZE - skip) :
+                    rand.nextInt(Integer.MAX_VALUE);
+            IntStream stream1 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            int[] toArray = stream1.substream(skip, skip + limit).toArray();
+            verifySlice(array, toArray, skip, limit);
+
+            IntStream stream2 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            assertEquals(stream2.substream(skip, skip).toArray().length, 0);
+
+            IntStream stream3 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            int skipExceeded = bf.apply(ARRAY_SIZE, Integer.MAX_VALUE);
+            assertEquals(stream3.substream(skipExceeded, skipExceeded + 1).toArray().length, 0);
+
+            IntStream emptyStream = (p == ParallelType.Parallel) ? Arrays.parallelStream(new int[0])
+                    : (p == ParallelType.Sequential) ? Arrays.stream(new int[0]).sequential() :
+                    Arrays.stream(new int[0]);
+            //We should consider it as bug, it should throw Exception, will make
+            //sure when all code finalized
+            assertEquals(emptyStream.substream(skip, skip + limit).toArray().length, 0);
+        }
+    }
+
+    @Test
+    public void testSorted() throws Exception{
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            final int[] array = generateData(ARRAY_SIZE);
+            IntStream stream = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            checkSorted(stream.sorted().toArray());
+
+            IntStream emptyStream = (p == ParallelType.Parallel) ? Arrays.parallelStream(new int[0])
+                    : (p == ParallelType.Sequential) ? Arrays.stream(new int[0]).sequential() :
+                    Arrays.stream(new int[0]);
+            //We should consider it as bug, it should throw Exception, will make
+            //sure when all code finalized
+            assertEquals(emptyStream.sorted().toArray().length, 0);
+        }
+    }
+
+    @Test
+    public void testPeek() throws Exception{
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            int[] array = generateData(ARRAY_SIZE);
+            IntStream stream1 = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            AtomicLong ai1 = new AtomicLong(0);
+            long sum = stream1.peek(LambdaUtilities.addLongConsumer(ai1)).sum();
+            assertEquals(ai1.get(), sum);
+
+            IntStream emptyStream = (p == ParallelType.Parallel) ? Arrays.parallelStream(new int[0]):
+                    (p == ParallelType.Sequential) ? Arrays.stream(new int[0]).sequential() :
+                    Arrays.stream(new int[0]);
+            assertFalse(emptyStream.peek(LambdaUtilities.addLongConsumer(ai1)).iterator().hasNext());
+            assertEquals(ai1.get(), sum);
+        }
+    }
+
+    @Test
+    public void testToArray() throws Exception{
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            int[] array = generateData(ARRAY_SIZE);
+            IntStream stream = (p == ParallelType.Parallel) ? Arrays.parallelStream(array)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array).sequential() :
+                    Arrays.stream(array);
+            int[] toArray = stream.toArray();
+            assertEquals(toArray, array);
+
+            IntStream emptyStream = (p == ParallelType.Parallel) ? Arrays.parallelStream(new int[0]):
+                    (p == ParallelType.Sequential) ? Arrays.stream(new int[0]).sequential() :
+                    Arrays.stream(new int[0]);
+            assertEquals(emptyStream.toArray().length, 0);
+        }
+    }
+
+    @Test
+    public void testUniqueElements() throws Exception{
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType p = it.next();
+            //Sometimes we can find duplicate value in array generated by
+            //generateData, this could be a Random's bug, need track it in other
+            //test
+            int[] array1 = Arrays.stream(generateData(ARRAY_SIZE)).distinct().toArray();
+            IntStream stream = (p == ParallelType.Parallel) ? Arrays.parallelStream(array1)
+                    : (p == ParallelType.Sequential) ? Arrays.stream(array1).sequential() :
+                    Arrays.stream(array1);
+            int[] toArray1 = stream.explode(LambdaUtilities.genFlatIntConsumer(4)).distinct().toArray();
+            assertEquals(toArray1, array1);
+
+            IntStream emptyStream = (p == ParallelType.Parallel) ? Arrays.parallelStream(new int[0]):
+                    (p == ParallelType.Sequential) ? Arrays.stream(new int[0]).sequential() :
+                    Arrays.stream(new int[0]);
+            assertEquals(emptyStream.explode(LambdaUtilities.genFlatIntConsumer(4)).distinct().toArray().length, 0);
+        }
+    }
+
+    private void verifyMultifunction(int[] orig, int[] result, int selected) throws Exception{
+        switch(selected) {
+            case 0:
+                assertEquals(result.length, 0);
+                break;
+            case 1:
+                assertEquals(orig, result);
+                break;
+            case 2:
+                int expectedSize = orig.length * (orig.length + 1) / 2;
+                int[] expected = Streams.intRange(0, expectedSize).toArray();
+                assertEquals(expected, result);
+                break;
+            case 3:
+            case 4:
+                List<Integer> empty = new ArrayList<>();
+
+                Stream<Integer> sToBeConcated = empty.stream();
+
+                for(int i = 0; i < orig.length; i++){
+                    final int i1 = i;
+                    sToBeConcated = Streams.concat(sToBeConcated, Streams.generateInt(() -> i1 + 1).limit(selected == 3 ? i + 1 : 1 << 6).boxed());
+                }
+                Iterator<Integer>  is = sToBeConcated.iterator();
+                int pos = 0;
+                while(is.hasNext()){
+                    assertEquals(is.next().intValue() , result[pos++]);
+                }
+                assertEquals(pos, result.length);
+                break;
+            default:
+                break;
+        }
+    }
+
+    private int getMax1(int[] array) {
+        assert(array.length > 0);
+        int pos = 0;
+        int max = array[pos++];
+        while(pos < array.length) {
+            int current = array[pos++];
+            if(max < current) max = current;
+        }
+        return max;
+    }
+
+    private int getMax2(int[] array) {
+        assert(array.length > 0);
+        OptionalInt max = Arrays.stream(array).reduce(LambdaUtilities.maxIntBinaryOperator());
+        return max.getAsInt();
+    }
+
+    private int getMax3(int[] array) {
+        assert(array.length > 0);
+        int max = Arrays.stream(array).reduce(array[0], LambdaUtilities.maxIntBinaryOperator());
+        return max;
+    }
+
+    private int getMin1(int[] array) {
+        assert(array.length > 0);
+        int pos = 0;
+        int min = array[pos++];
+        while(pos < array.length) {
+            int current = array[pos++];
+            if(min > current) min = current;
+        }
+        return min;
+    }
+
+    private int getMin2(int[] array) {
+        assert(array.length > 0);
+        OptionalInt min = Arrays.stream(array).reduce(LambdaUtilities.minIntBinaryOperator());
+        return min.getAsInt();
+    }
+
+    private int getMin3(int[] array) {
+        assert(array.length > 0);
+        int min = Arrays.stream(array).reduce(array[0], LambdaUtilities.minIntBinaryOperator());
+        return min;
+    }
+
+    private void verifySlice(int[] array, int[] toArray, int skip, int limit){
+        for(int index = skip; index < array.length && index < limit + skip;
+                index++)
+            assertTrue(array[index] <= toArray[index - skip]);
+    }
+
+    private void verifyAfterOps(int[] org, int[] afterOps, LambdaUtilities.IntOp op,
+            int value) {
+        assertEquals(org.length, afterOps.length);
+        for(int index = 0; index < org.length; index++) {
+            int expected = org[index];
+            if(value != 0) {
+                switch (op) {
+                    case ADD:
+                        expected += value;
+                        break;
+                    case SUBTRACT:
+                        expected -= value;
+                        break;
+                    case MULTIPLY:
+                        expected *= value;
+                        break;
+                    case DIVIDE:
+                        expected /= value;
+                        break;
+                    default:
+                        expected %= value;
+                        break;
+                }
+            }
+            assertEquals(expected, afterOps[index]);
+        }
+
+    }
+
+    private void checkSorted(int[] array){
+        assert(array.length > 0);
+        for(int index = 0; index < array.length - 1; index++)
+            assertTrue(array[index] <= array[index + 1]);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/stream/Stream/IntegerStreamTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,1150 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Basic test for Stream<Integer>
+ * @library ../..
+ * @(#) IntegerStreamTest.java
+ * @author Tristan Yan
+ * @run testng IntegerStreamTest
+ */
+
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.BiFunction;
+import java.util.function.Predicate;
+import java.util.function.Predicates;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.Streams;
+import static org.testng.Assert.*;
+import org.testng.ITest;
+import org.testng.annotations.Factory;
+import org.testng.annotations.Test;
+
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class IntegerStreamTest<T extends Collection<Integer>> implements ITest {
+    enum ParallelType { Parallel, Sequential, Default};
+
+    private final static int START = -1 << 6;
+
+    private final static int END = 1 << 6;
+
+    private final static Random rand = new Random(System.currentTimeMillis());
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    private static Class[] defaultConstructorClazz = {
+        (Class<ArrayDeque<Integer>>)(Class<?>)(ArrayDeque.class),
+        (Class<ArrayList<Integer>>)(Class<?>)(ArrayList.class),
+        (Class<ConcurrentLinkedDeque<Integer>>)(Class<?>)(ConcurrentLinkedDeque.class),
+        (Class<ConcurrentLinkedQueue<Integer>>)(Class<?>)(ConcurrentLinkedQueue.class),
+        (Class<ConcurrentSkipListSet<Integer>>)(Class<?>)(ConcurrentSkipListSet.class),
+        (Class<CopyOnWriteArrayList<Integer>>)(Class<?>)(CopyOnWriteArrayList.class),
+        (Class<HashSet<Integer>>)(Class<?>)(HashSet.class),
+        (Class<LinkedBlockingDeque<Integer>>)(Class<?>)(LinkedBlockingDeque.class),
+        (Class<LinkedBlockingQueue<Integer>>)(Class<?>)(LinkedBlockingQueue.class),
+        (Class<LinkedHashSet<Integer>>)(Class<?>)(LinkedHashSet.class),
+        (Class<LinkedList<Integer>>)(Class<?>)(LinkedList.class),
+        (Class<LinkedTransferQueue<Integer>>)(Class<?>)(LinkedTransferQueue.class),
+        (Class<PriorityBlockingQueue<Integer>>)(Class<?>)(PriorityBlockingQueue.class),
+        (Class<PriorityQueue<Integer>>)(Class<?>)(PriorityQueue.class),
+        (Class<Stack<Integer>>)(Class<?>)(Stack.class),
+        (Class<TreeSet<Integer>>)(Class<?>)(TreeSet.class),
+        (Class<Vector<Integer>>)(Class<?>)(Vector.class)
+    };
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    private static Class[] capacityConstructorClazz = {
+        (Class<ArrayBlockingQueue<Integer>>)(Class<?>)(ArrayBlockingQueue.class),
+        (Class<ArrayDeque<Integer>>)(Class<?>)(ArrayDeque.class),
+        (Class<ArrayList<Integer>>)(Class<?>)(ArrayList.class),
+        (Class<HashSet<Integer>>)(Class<?>)(HashSet.class),
+        (Class<LinkedBlockingDeque<Integer>>)(Class<?>)(LinkedBlockingDeque.class),
+        (Class<LinkedBlockingQueue<Integer>>)(Class<?>)(LinkedBlockingQueue.class),
+        (Class<LinkedHashSet<Integer>>)(Class<?>)(LinkedHashSet.class),
+        (Class<PriorityBlockingQueue<Integer>>)(Class<?>)(PriorityBlockingQueue.class),
+        (Class<PriorityQueue<Integer>>)(Class<?>)(PriorityQueue.class),
+        (Class<Vector<Integer>>)(Class<?>)(Vector.class)
+    };
+
+    private Class<T> typeObject;
+
+    private boolean hasIni;
+
+    private int initSize;
+
+    public IntegerStreamTest(Class<T> clazz, int... initSizes) {
+        this.typeObject = clazz;
+        assert(initSizes.length <= 1);
+        if(initSizes.length == 1) {
+            hasIni = true;
+            this.initSize = initSizes[0];
+        }
+    }
+
+    @Factory
+    public static Object[] create(){
+        List<IntegerStreamTest> result = new ArrayList<>();
+        Stream<Class> stream1 = Arrays.stream(defaultConstructorClazz);
+        Stream<Class> stream2 = Arrays.stream(capacityConstructorClazz);
+        stream1.forEach(clazz -> result.add(new IntegerStreamTest(clazz)));
+        stream2.forEach(clazz -> result.add(new IntegerStreamTest(clazz,
+                END - START + rand.nextInt(END - START))));
+        return result.toArray();
+    }
+
+    @Override
+    public String getTestName() {
+        return typeObject.getName() + "<Integer>";
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testAllMatch() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Integer> c1 =  generateData(START, END);
+            int limit = rand.nextInt(2 * (END - START)) + 2 * START;
+            boolean isUP = rand.nextBoolean();
+            Stream<Integer> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream():
+                    (type == ParallelType.Sequential) ? c1.stream().sequential() :
+                    c1.stream();
+            assertEquals(stream1.allMatch(LambdaUtilities.randomIntegerPredicate(isUP, limit)),
+                    verifyMatch(c1, limit, isUP, true));
+
+            //Empty stream's allMatch  will return true always
+            @SuppressWarnings("cast")
+            Collection<Integer> emptyCol =  hasIni ?
+                    (Collection<Integer>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Integer>)LambdaUtilities.create(typeObject);
+            Stream<Integer> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                    emptyCol.stream();
+            assertTrue(stream2.allMatch(LambdaUtilities.randomIntegerPredicate(isUP, limit)));
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testAnyMatch() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Integer> c1 =  generateData(START, END);
+            int limit = rand.nextInt(2 * (END - START)) + 2 * START;
+            boolean isUP = rand.nextBoolean();
+            Stream<Integer> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream():
+                    (type == ParallelType.Sequential) ? c1.stream().sequential() :
+                    c1.stream();
+            assertEquals(stream1.anyMatch(LambdaUtilities.randomIntegerPredicate(isUP, limit)),
+                    verifyMatch(c1, limit, isUP, false));
+
+            //Empty stream's anyMatch, noneMatch will return false always
+            @SuppressWarnings("cast")
+            Collection<Integer> emptyCol =  hasIni ?
+                    (Collection<Integer>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Integer>)LambdaUtilities.create(typeObject);
+            Stream<Integer> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                    emptyCol.stream();
+            assertTrue(!stream2.anyMatch(LambdaUtilities.randomIntegerPredicate(isUP, limit)));
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testConcat() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            //Concate two list's stream, then filter one predicate should be expect
+            //to be same as filter two stream repectively then concate the result.
+            Collection<Integer> l1 =  generateData(START, END);
+            Collection<Integer> l2 =  generateData(START, END);
+            int limit = rand.nextInt(2 * (END - START)) + 2 * START;
+            boolean isUP = rand.nextBoolean();
+            Predicate<Integer> p = LambdaUtilities.randomIntegerPredicate(isUP, limit);
+            Stream<Integer> stream11 = (type == ParallelType.Parallel) ? l1.parallelStream():
+                    (type == ParallelType.Sequential) ? l1.stream().sequential() :
+                    l1.stream();
+            Stream<Integer> stream21 = (type == ParallelType.Parallel) ? l2.parallelStream():
+                    (type == ParallelType.Sequential) ? l2.stream().sequential() :
+                    l2.stream();
+            Collection<Integer> result1 = stream11.filter(p).collect(Collectors.toCollection(LinkedList<Integer>::new));
+            Collection<Integer> result2 = stream21.filter(p).collect(Collectors.toCollection(LinkedList<Integer>::new));
+            result1.addAll(result2);
+
+            Stream<Integer> stream12 = (type == ParallelType.Parallel) ? l1.parallelStream():
+                    (type == ParallelType.Sequential) ? l1.stream().sequential() :
+                    l1.stream();
+            Stream<Integer> stream22 = (type == ParallelType.Parallel) ? l2.parallelStream():
+                    (type == ParallelType.Sequential) ? l2.stream().sequential() :
+                    l2.stream();
+            List<Integer> expectedList = Streams.concat(stream12, stream22).filter(p).collect(Collectors.<Integer>toList());
+            List<Integer> testList = new ArrayList<Integer>(result1);
+            Collections.sort(testList);
+            Collections.sort(expectedList);
+            assertEquals(testList, expectedList);
+
+            Collection<Integer> emptyList = hasIni ? LambdaUtilities.create(typeObject, initSize)
+                : LambdaUtilities.create(typeObject);
+            Stream<Integer> stream3 = (type == ParallelType.Parallel) ? emptyList.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyList.stream().sequential() :
+                    emptyList.stream();
+            List<Integer> result3 = Streams.concat(l1.stream(), stream3).collect(Collectors.<Integer>toList());
+            List<Integer> list1 = new ArrayList<Integer>(l1);
+            Collections.sort(list1);
+            Collections.sort(result3);
+            assertEquals(list1, result3);
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testFilter() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            //Create predicate with random limit and random up/down size
+            Collection<Integer> l =  generateData(START, END);
+            Stream<Integer> stream = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+            stream = l.stream();
+            int limit1 = rand.nextInt(2 * (END - START)) + 2 * START;
+            boolean isUP1 = rand.nextBoolean();
+            Predicate<Integer> p1 = LambdaUtilities.randomIntegerPredicate(isUP1, limit1);
+
+            //Filter the data, check if it works as expected.
+            @SuppressWarnings("cast")
+            Collection<Integer> result1 = stream.filter(p1).collect(Collectors.toCollection(LinkedList<Integer>::new));
+            assertTrue(verifyMatch(result1, limit1, isUP1, true));
+
+            //filter on parallel stream can cause IllegalStateException
+            stream = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+            result1.clear();
+            result1 = stream.filter(p1).filter(Predicates.alwaysTrue()).collect(Collectors.toCollection(LinkedList<Integer>::new));
+            assertTrue(verifyMatch(result1, limit1, isUP1, true));
+
+            //filter with Predicates.alwaysFlase() will get nothing
+            stream = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+            result1.clear();
+            result1 = stream.filter(p1).filter(Predicates.alwaysFalse()).collect(Collectors.toCollection(LinkedList<Integer>::new));
+            assertTrue(result1.size() == 0);
+
+            int limit2 = rand.nextInt(2 * (END - START)) + 2 * START;
+            boolean isUP2 = rand.nextBoolean();
+            Predicate<Integer> p2 = LambdaUtilities.randomIntegerPredicate(isUP2, limit2);
+            int limit3 = rand.nextInt(2 * (END - START)) + 2 * START;
+            boolean isUP3 = rand.nextBoolean();
+            Predicate<Integer> p3 = LambdaUtilities.randomIntegerPredicate(isUP3, limit3);
+            //The reason conver l to sorted is CopyOnWriteArrayList doesn't support
+            //sort, we use ArrayList sort data instead
+            stream = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+            List<Integer> result2 = stream.filter(p1).filter(p2).collect(Collectors.<Integer>toList());
+            stream = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+            List<Integer> result3 = stream.filter(Predicates.and(p1,p2)).collect(Collectors.<Integer>toList());
+            Comparator<Integer> c = (Comparator<Integer>)Comparators.naturalOrder();
+            Collections.sort(result2, c);
+            Collections.sort(result3, c);
+            assertEquals(result2, result3);
+            result2.clear();
+            result3.clear();
+
+            stream = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+            result2 = stream.filter(Predicates.and(p1,p2)).collect(Collectors.<Integer>toList());
+            stream = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+            result3 = stream.filter(Predicates.or(p1,p2)).collect(Collectors.<Integer>toList());
+            result2.addAll(result3);
+            result3.clear();
+            stream = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+            Stream<Integer>  stream2 = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+            result3 = Streams.concat(stream.filter(p1), stream2.filter(p2)).collect(Collectors.<Integer>toList());
+            Collections.sort(result2, c);
+            Collections.sort(result3, c);
+            assertEquals(result2, result3);
+
+            @SuppressWarnings("cast")
+            Collection<Integer> emptyList  =  hasIni ?
+                    (Collection<Integer>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Integer>)LambdaUtilities.create(typeObject);
+            Stream<Integer> stream3 = (type == ParallelType.Parallel) ? emptyList.parallelStream():
+                (type == ParallelType.Sequential) ? emptyList.stream().sequential() :
+                emptyList.stream();
+            assertFalse(stream3.filter(p1).iterator().hasNext());
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testFind() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Integer> c =  generateData(START, END);
+            Stream<Integer> stream1 = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+            Stream<Integer> stream2 = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+            java.util.Optional<Integer> opAny = stream1.findAny();
+            java.util.Optional<Integer> opFirst = stream2.findFirst();
+            assertTrue(opAny.isPresent());
+            assertTrue(opFirst.isPresent());
+            if(!stream1.isParallel())
+                assertEquals(opAny, opFirst);
+
+            @SuppressWarnings("cast")
+            Collection<Integer> emptyCol =  hasIni ?
+                    (Collection<Integer>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Integer>)LambdaUtilities.create(typeObject);
+            Stream<Integer> emptyStream1 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                    emptyCol.stream();
+            java.util.Optional<Integer> emptyAny = emptyStream1.findAny();
+            assertFalse(emptyAny.isPresent());
+            Stream<Integer> emptyStream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                    emptyCol.stream();
+            java.util.Optional<Integer> emptyFirsty = emptyStream2.findFirst();
+            assertFalse(emptyFirsty.isPresent());
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testForEach() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Integer> c =  generateData(START, END);
+            Stream<Integer> stream1 = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+            stream1.forEach(t -> { assertTrue(c.contains(t)); });
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testForEachUntil() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Integer> c =  generateData(START, END);
+            final int limit = rand.nextInt(c.size());
+            final Collection<Integer> cLimit =  hasIni ?
+                    LambdaUtilities.create(typeObject, initSize) :
+                    LambdaUtilities.create(typeObject);
+            Stream<Integer> stream1 = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+            stream1.forEachUntil(t -> cLimit.add(t), () -> cLimit.size() == limit);
+            assertEquals(cLimit.size(), limit);
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testCollect() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Integer> c =  generateData(START, END);
+
+            boolean isHighest = rand.nextBoolean();
+            Stream<Integer> stream = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+            Map<Integer, Collection<Integer>> result
+                    = stream.collect(Collectors.groupingBy(LambdaUtilities.posIntegerFunction(isHighest)));
+            verifyGroupBy(result, isHighest);
+
+            @SuppressWarnings("cast")
+            Collection<Integer> emptyList = hasIni ?
+                    (Collection<Integer>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Integer>)LambdaUtilities.create(typeObject);
+            Stream<Integer> stream2 = (type == ParallelType.Parallel) ? emptyList.parallelStream():
+                (type == ParallelType.Sequential) ? emptyList.stream().sequential() :
+                emptyList.stream();
+            assertTrue(stream2.collect(Collectors.groupingBy(LambdaUtilities.posIntegerFunction(isHighest))).isEmpty());
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testLimit() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            @SuppressWarnings("cast")
+            Collection<Integer> c = hasIni ?
+                    (Collection<Integer>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Integer>)LambdaUtilities.create(typeObject);
+            for(int i = 0; i < END; i++) {
+                c.add(i);
+            }
+            int limit = rand.nextInt(END * (END - 1));
+            Stream<Integer> stream1 = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+            Collection<Integer> result1 = stream1.explode(LambdaUtilities.genIntegerFlatBiConsumer(2)).collect(Collectors.toCollection(LinkedList<Integer>::new));
+
+            Stream<Integer> stream2 = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+            Collection<Integer> result2 = stream2.explode(LambdaUtilities.genIntegerFlatBiConsumer(2)).limit(limit).collect(Collectors.toCollection(LinkedList<Integer>::new));
+
+            if(limit > result1.size())
+                assertEquals(result1.size(), result2.size());
+            else {
+                assertEquals(result2.size(), limit);
+            }
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testExplode() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            @SuppressWarnings("cast")
+            Collection<Integer> c = hasIni ?
+                    (Collection<Integer>)LambdaUtilities.create(typeObject, initSize * initSize) :
+                    (Collection<Integer>)LambdaUtilities.create(typeObject);
+            for(int i = 0; i < END; i++) {
+                c.add(i);
+            }
+            int selected = rand.nextInt(4);
+            Stream<Integer> stream = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+            List<Integer> result = stream.explode(LambdaUtilities.genIntegerFlatBiConsumer(selected)).collect(Collectors.<Integer>toList());
+            verifyMultifunction(c, result, selected);
+        }
+    }
+
+    @Test
+    public void testMap() throws Exception {
+        Iterator<ParallelType> it = EnumSet.allOf(ParallelType.class).iterator();
+        while(it.hasNext()) {
+            ParallelType type = it.next();
+            Collection<Integer> c =  generateData(START, END);
+            Stream<Integer> stream1 = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+
+            int randOps = rand.nextInt();
+            int selected = rand.nextInt(5);
+            LambdaUtilities.IntOp op = LambdaUtilities.IntOp.values()[selected];
+            Iterator<Integer> itOrg = c.iterator();
+            Iterator<Integer> itResult1 = stream1.map(LambdaUtilities.opIntegerFunction(op, randOps)).iterator();
+            while(itResult1.hasNext() && itOrg.hasNext()) {
+                Integer expected = itOrg.next();
+                if(randOps != 0) {
+                    switch (op) {
+                        case ADD:
+                            expected += randOps;
+                            break;
+                        case SUBTRACT:
+                            expected -= randOps;
+                            break;
+                        case MULTIPLY:
+                            expected *= randOps;
+                            break;
+                        case DIVIDE:
+                            expected /= randOps;
+                            break;
+                        default:
+                            expected %= randOps;
+                            break;
+                    }
+                }
+                assertEquals(itResult1.next(), expected);
+            }
+            assertEquals(itResult1.hasNext(), itOrg.hasNext());
+
+            Stream<Integer> stream2 = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+            PrimitiveIterator<Integer> pit = stream2.map(LambdaUtilities.opToIntFunction(op, randOps)).iterator();
+            verifyAfterOps(c.iterator(), pit, op, randOps);
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testMax() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        Comparator<Integer> c1 = (Comparator<Integer>)Comparators.naturalOrder();
+        Comparator<Integer> c2 = (Comparator<Integer>)Comparators.reverseOrder();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Integer> col1 =  generateData(START, END);
+            int limit = rand.nextInt(2 * (END - START)) + 2 * START;
+            boolean isUP = rand.nextBoolean();
+            Stream<Integer> stream1 = (type == ParallelType.Parallel) ? col1.parallelStream():
+                    (type == ParallelType.Sequential) ? col1.stream().sequential() :
+                    col1.stream();
+            java.util.Optional<Integer> optional1 = stream1.max(c1);
+            assertTrue(optional1.isPresent());
+            assertTrue(optional1.get() == getMax1(col1, c1));
+            Stream<Integer> stream2 = (type == ParallelType.Parallel) ? col1.parallelStream():
+                    (type == ParallelType.Sequential) ? col1.stream().sequential() :
+                    col1.stream();
+            java.util.Optional<Integer> optional2 = stream2.max(c2);
+            assertTrue(optional2.isPresent());
+            assertTrue(optional2.get() == getMax1(col1, c2));
+            assertTrue(optional2.get() == getMax2(col1, c2));
+            assertTrue(optional2.get() == getMax3(col1, c2));
+            assertTrue(optional2.get() == getMax4(col1, c2));
+
+            @SuppressWarnings("cast")
+            Collection<Integer> emptyCol =  hasIni ?
+                    (Collection<Integer>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Integer>)LambdaUtilities.create(typeObject);
+            Stream<Integer> stream3 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                    emptyCol.stream();
+            assertFalse(stream3.max(c1).isPresent());
+            Stream<Integer> stream4= (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                    emptyCol.stream();
+            assertFalse(stream4.max(c2).isPresent());
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testMin() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        Comparator<Integer> c1 = (Comparator<Integer>)Comparators.naturalOrder();
+        Comparator<Integer> c2 = (Comparator<Integer>)Comparators.reverseOrder();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Integer> col1 =  generateData(START, END);
+            Stream<Integer> stream1 = (type == ParallelType.Parallel) ? col1.parallelStream():
+                    (type == ParallelType.Sequential) ? col1.stream().sequential() :
+                    col1.stream();
+            java.util.Optional<Integer> optional1 = stream1.min(c1);
+            assertTrue(optional1.isPresent());
+            assertTrue(optional1.get() == getMin1(col1, c1));
+            Stream<Integer> stream2 = (type == ParallelType.Parallel) ? col1.parallelStream():
+                    (type == ParallelType.Sequential) ? col1.stream().sequential() :
+                    col1.stream();
+            java.util.Optional<Integer> optional2 = stream2.min(c2);
+            assertTrue(optional2.isPresent());
+            assertTrue(optional2.get() == getMin1(col1, c2));
+            assertTrue(optional2.get() == getMin2(col1, c2));
+            assertTrue(optional2.get() == getMin3(col1, c2));
+            assertTrue(optional2.get() == getMin4(col1, c2));
+
+            @SuppressWarnings("cast")
+            Collection<Integer> emptyCol =  hasIni ?
+                    (Collection<Integer>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Integer>)LambdaUtilities.create(typeObject);
+            Stream<Integer> stream3 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                    emptyCol.stream();
+            assertFalse(stream3.min(c1).isPresent());
+            Stream<Integer> stream4 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                    emptyCol.stream();
+            assertFalse(stream4.min(c2).isPresent());
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testNoneMatch() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Integer i = 10;
+            Collection<Integer> c1 =  generateData(START, END);
+            int limit = rand.nextInt(2 * (END - START)) + 2 * START;
+            boolean isUP = rand.nextBoolean();
+            Stream<Integer> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream():
+                    (type == ParallelType.Sequential) ? c1.stream().sequential() :
+                    c1.stream();
+            assertEquals(stream1.noneMatch(LambdaUtilities.randomIntegerPredicate(isUP, limit)),
+                    verifyMatch(c1, limit, !isUP, true));
+
+            //Empty stream's noneMatch will return true always
+            @SuppressWarnings("cast")
+            Collection<Integer> emptyCol =  hasIni ?
+                    (Collection<Integer>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Integer>)LambdaUtilities.create(typeObject);
+            Stream<Integer> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                    emptyCol.stream();
+            assertTrue(stream2.noneMatch(LambdaUtilities.randomIntegerPredicate(isUP, limit)));
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testReduceWithoutBase() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Integer> col1 =  generateData(START, END - 1);
+            //
+            Stream<Integer> streamPlus = (type == ParallelType.Parallel) ? col1.parallelStream():
+                    (type == ParallelType.Sequential) ? col1.stream().sequential() :
+                    col1.stream();
+            java.util.Optional<Integer> oiPlus = streamPlus.reduce(LambdaUtilities.addIntegerBinaryOperator());
+            assertTrue(oiPlus.isPresent());
+            int total = 0;
+            Iterator<Integer> it1 = col1.iterator();
+            while(it1.hasNext())
+                total += it1.next();
+            assertTrue(oiPlus.get() == total);
+
+            Stream<Integer> streamSubtract = (type == ParallelType.Parallel) ? col1.parallelStream():
+                    (type == ParallelType.Sequential) ? col1.stream().sequential() :
+                    col1.stream();
+            java.util.Optional<Integer> oiSubtract = streamSubtract.reduce(LambdaUtilities.subIntegerBinaryOperator());
+            assertTrue(oiSubtract.isPresent());
+
+            //Can't predict Parallel Substract reduce result, give up testing on
+            //parallel substract test
+            if(type == ParallelType.Parallel)
+                continue;
+
+            Iterator<Integer> it2 = col1.iterator();
+            int subTotal = it2.next();
+            while(it2.hasNext())
+                subTotal -= it2.next();
+            assertTrue(oiSubtract.get() == subTotal);
+
+            @SuppressWarnings("cast")
+            Collection<Integer> emptyCol = hasIni ?
+                    (Collection<Integer>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Integer>)LambdaUtilities.create(typeObject);
+            Stream<Integer> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                    emptyCol.stream();
+            java.util.Optional<Integer> emptyOp = stream2.reduce(rand.nextBoolean() ?
+                    LambdaUtilities.addIntegerBinaryOperator() :
+                    LambdaUtilities.subIntegerBinaryOperator());
+            assertFalse(emptyOp.isPresent());
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testReduceIdentitiyWithoutBase() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Integer> col =  generateData(START, END - 1);
+            Stream<Integer> streamTotal = (type == ParallelType.Parallel) ? col.parallelStream():
+                    (type == ParallelType.Sequential) ? col.stream().sequential() :
+                    col.stream();
+            java.util.Optional<Integer> total = streamTotal.reduce(LambdaUtilities.addIntegerBinaryOperator());
+            double avg = (double)total.get().intValue() / col.size();
+            Stream<Integer> streamStanDeviation = (type == ParallelType.Parallel) ? col.parallelStream():
+                    (type == ParallelType.Sequential) ? col.stream().sequential() :
+                    col.stream();
+           BigDecimal deviationSquare = streamStanDeviation.reduce(new BigDecimal(0.0), LambdaUtilities.deviationSequareFunction(avg), LambdaUtilities.addBigDecimalBinaryOperator());
+           double stdev = deviationSquare.doubleValue() / col.size();
+
+           int totalExpected = 0;
+           Iterator<Integer> itTotal = col.iterator();
+           while(itTotal.hasNext())
+                totalExpected +=  itTotal.next();
+           assertEquals(totalExpected, total.get().intValue());
+           double avgExpected = (double)totalExpected / col.size();
+           assertEquals(avgExpected, avg);
+
+           BigDecimal deviationSquareExpected = new BigDecimal(0.0);
+           Iterator<Integer> itDeviationSquare  = col.iterator();
+           while(itDeviationSquare.hasNext()) {
+               int v = itDeviationSquare.next();
+               deviationSquareExpected = deviationSquareExpected.add(new BigDecimal(avg - v).pow(2)) ;
+           }
+           assertEquals(deviationSquare, deviationSquareExpected);
+
+           double stddvExpected = deviationSquareExpected.doubleValue() / col.size();
+           assertEquals(stddvExpected, stdev);
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testReduceWithBase() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            //Can't predict Parallel Add/Substract reduce result, give up
+            //testing on parallel substract test
+            if(type == ParallelType.Parallel)
+                continue;
+            Collection<Integer> col1 =  generateData(START, END - 1);
+
+            int base = rand.nextInt(END - START) + START;
+            Stream<Integer> streamPlus = (type == ParallelType.Parallel) ? col1.parallelStream():
+                    (type == ParallelType.Sequential) ? col1.stream().sequential() :
+                    col1.stream();
+            int oiPlus = streamPlus.reduce(base, LambdaUtilities.addIntegerBinaryOperator());
+            int total = base;
+
+            Iterator<Integer> it1 = col1.iterator();
+            while(it1.hasNext())
+                total += it1.next();
+            assertEquals(oiPlus, total);
+
+            Stream<Integer> streamSubtract = (type == ParallelType.Parallel) ? col1.parallelStream():
+                    (type == ParallelType.Sequential) ? col1.stream().sequential() :
+                    col1.stream();
+            int oiSub = streamSubtract.reduce(base, LambdaUtilities.subIntegerBinaryOperator());
+
+            int subTotal = base;
+            Iterator<Integer> it2 = col1.iterator();
+            while(it2.hasNext())
+                subTotal -= it2.next();
+            assertEquals(subTotal, oiSub);
+
+            @SuppressWarnings("cast")
+            Collection<Integer> emptyCol  = hasIni ?
+                    (Collection<Integer>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Integer>)LambdaUtilities.create(typeObject);;
+            Stream<Integer> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                    emptyCol.stream();
+            int emptyOp = stream2.reduce(base, rand.nextBoolean() ?
+                    LambdaUtilities.addIntegerBinaryOperator() :
+                    LambdaUtilities.subIntegerBinaryOperator());
+            assertEquals(emptyOp, base);
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testSubstream() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        BiFunction<Integer,Integer, Integer> bf = LambdaUtilities.randBetweenIntegerFunction();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Integer> col =  generateData(START, END);
+            int skip = rand.nextInt(col.size());
+            //limit has more than 50% chance less than col.size() - skip
+            int limit = rand.nextBoolean() ?
+                    bf.apply(0, col.size() - skip) :
+                    rand.nextInt(Integer.MAX_VALUE);
+            Stream<Integer> stream1 = (type == ParallelType.Parallel) ? col.parallelStream():
+                    (type == ParallelType.Sequential) ? col.stream().sequential() :
+                    col.stream();
+            Iterator<Integer> it = stream1.substream(skip, skip + limit).iterator();
+            verifySlice(col.iterator(), it, skip, limit);
+
+            //limit=0 causes empty stream
+            Stream<Integer> stream2 = (type == ParallelType.Parallel) ? col.parallelStream():
+                    (type == ParallelType.Sequential) ? col.stream().sequential() :
+                    col.stream();
+            assertFalse(stream2.substream(skip, skip).iterator().hasNext());
+
+            //skip exceed collection size cause  empty stream
+            Stream<Integer> stream3 = (type == ParallelType.Parallel) ? col.parallelStream():
+                    (type == ParallelType.Sequential) ? col.stream().sequential() :
+                    col.stream();
+            int skipExceeded = bf.apply(col.size(), Integer.MAX_VALUE);
+            assertFalse(stream3.substream(skipExceeded, skipExceeded + 1).iterator().hasNext());
+
+            @SuppressWarnings("cast")
+            Collection<Integer> emptyCol  = hasIni ?
+                    (Collection<Integer>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Integer>)LambdaUtilities.create(typeObject);
+            Stream<Integer> emptyStream = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                emptyCol.stream();
+            assertFalse(emptyStream.substream(skip, skip + limit).iterator().hasNext());
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testSorted() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Integer> col =  generateData(START, END);
+            Stream<Integer> stream = (type == ParallelType.Parallel) ? col.parallelStream():
+                    (type == ParallelType.Sequential) ? col.stream().sequential() :
+                    col.stream();
+            List<Integer> reversed = stream.sorted((Comparator<Integer>)Comparators.reverseOrder()).collect(Collectors.<Integer>toList());
+            //The reason conver l to sorted is CopyOnWriteArrayList doesn't support
+            //sort, we use ArrayList sort data instead
+            List<Integer> sorted = new ArrayList<>(col);
+            Collections.sort(sorted);
+
+            //SortedSet instance's stream can't be reordered
+            if(!(col instanceof SortedSet))
+                Collections.reverse(sorted);
+            assertEquals(sorted, reversed);
+
+            @SuppressWarnings("cast")
+            Collection<Integer> emptyCol  = hasIni ?
+                    (Collection<Integer>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Integer>)LambdaUtilities.create(typeObject);
+            Stream<Integer> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                emptyCol.stream();
+            assertFalse(stream2.sorted(Collections.reverseOrder()).iterator().hasNext());
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testPeek() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Integer> c1 =  generateData(START, END);
+            Stream<Integer> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream():
+                    (type == ParallelType.Sequential) ? c1.stream().sequential() :
+                    c1.stream();
+            Stream<Integer> stream2 = (type == ParallelType.Parallel) ? c1.parallelStream():
+                    (type == ParallelType.Sequential) ? c1.stream().sequential() :
+                    c1.stream();
+            AtomicInteger ai1 = new AtomicInteger(0);
+            Iterator<Integer> it = stream1.peek(LambdaUtilities.addIntegerConsumer(ai1)).iterator();
+            int expectedTotal = 0;
+            while(it.hasNext())
+                expectedTotal += it.next();
+            assertEquals(ai1.get(), expectedTotal);
+            AtomicInteger ai2 = stream2.collect(LambdaUtilities.atomicIntegerSupplier(0),
+                    LambdaUtilities.addIntegerBiConsumer(),
+                    LambdaUtilities.addAtomicIntegerBiConsumer());
+            assertEquals(ai2.get(), expectedTotal);
+
+            @SuppressWarnings("cast")
+            Collection<Integer> emptyCol =  hasIni ?
+                    (Collection<Integer>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Integer>)LambdaUtilities.create(typeObject);
+            Stream<Integer> emptyStream = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                    emptyCol.stream();
+            assertFalse(emptyStream.peek(LambdaUtilities.addIntegerConsumer(ai1)).iterator().hasNext());
+            assertEquals(ai1.get(), expectedTotal);
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testToArray() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Integer> c1 =  generateData(START, END);
+            Stream<Integer> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream():
+                    (type == ParallelType.Sequential) ? c1.stream().sequential() :
+                    c1.stream();
+            Object[] arr1 = stream1.toArray();
+            Object[] arr2 = c1.toArray();
+            assert(arr1.length == arr2.length);
+            for(int index = 0; index < arr1.length; index++) {
+                assertEquals(arr1[index], arr2[index]);
+            }
+
+            @SuppressWarnings("cast")
+            Collection<Integer> emptyCol =  hasIni ?
+                    (Collection<Integer>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<Integer>)LambdaUtilities.create(typeObject);
+            Stream<Integer> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                    emptyCol.stream();
+            assertEquals(stream2.toArray().length, 0);
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testUniqueElements() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<Integer> c1 =  generateData(START, END);
+            Set<Integer> set1 = new HashSet<>(c1);
+            Stream<Integer> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream():
+                    (type == ParallelType.Sequential) ? c1.stream().sequential() :
+                    c1.stream();
+            List<Integer> list2 = stream1.explode(LambdaUtilities.genIntegerFlatBiConsumer(4)).distinct().collect(Collectors.<Integer>toList());
+            assertEquals(set1.size(), list2.size());
+            assertTrue(set1.containsAll(list2));
+        }
+    }
+
+    private Collection<Integer> generateData(int start, int end, int size)
+            throws Exception{
+        Collection<Integer> col = hasIni ? LambdaUtilities.create(typeObject, initSize)
+                : LambdaUtilities.create(typeObject);
+        for(int i = 0; i < size; i++) {
+            int element = start + rand.nextInt(end - start);
+            col.add(element);
+        }
+        return col;
+    }
+
+    private Collection<Integer> generateData(int start, int end) throws Exception{
+        return generateData(start, end, end - start);
+    }
+
+    private boolean verifyMatch(Collection<Integer> c, int limit, boolean isUP,
+            boolean all) {
+        Iterator<Integer> it = c.iterator();
+        while(it.hasNext()) {
+            int current = it.next();
+            if(isUP) {
+                if(all) {
+                    if(current < limit) return false;
+                } else {
+                    if(current >= limit) return true;
+                }
+            } else {
+                if(all) {
+                    if(current >= limit) return false;
+                } else {
+                    if(current < limit) return true;
+                }
+            }
+        }
+        return all;
+    }
+
+    private void verifyGroupBy(Map<Integer, Collection<Integer>> result, boolean isHighest){
+        assertTrue(result.size() <= 10);
+        Iterator<Integer> keyiter = result.keySet().iterator();
+        while(keyiter.hasNext()) {
+            int key = keyiter.next();
+            assertTrue(key < 10 && key >= 0);
+            Iterator<Integer> valueiter = result.get(key).iterator();
+            while(valueiter.hasNext()) {
+                int i = valueiter.next();
+                if(isHighest)
+                    assertTrue(Integer.valueOf(new StringBuilder().append(i < 0 ? -i : i).reverse().toString()) % 10 == key);
+                else
+                    assertTrue((i % 10 < 0 ? - i % 10 : i % 10) == key);
+            }
+        }
+    }
+
+    private void verifyMultifunction(Collection<Integer> orig, List<Integer> result,
+            int selected) throws Exception{
+        switch(selected) {
+            case 0:
+                assertEquals(result.size(), 0);
+                break;
+            case 1:
+                List<Integer> l1 = new ArrayList<>(orig);
+                Collections.sort(l1);
+                Collections.sort(result);
+                assertEquals(l1, result);
+                break;
+            case 2:
+                List<Integer> l2 = new ArrayList<>();
+                Iterator<Integer> it2 = orig.iterator();
+                while(it2.hasNext()) {
+                    int current = it2.next();
+                    for(int i = 0; i < current; i++)
+                        l2.add(i + current * (current - 1) / 2);
+                }
+                Collections.sort(l2);
+                Collections.sort(result);
+                assertEquals(l2, result);
+                break;
+            case 3:
+                List<Integer> l3 = new ArrayList<>();
+                Iterator<Integer> it3 = orig.iterator();
+                while(it3.hasNext()) {
+                    int current = it3.next();
+                    for(int i = 0; i < current; i++)
+                        l3.add(current);
+                }
+                Collections.sort(l3);
+                Collections.sort(result);
+                assertEquals(l3, result);
+                break;
+            default:
+                break;
+        }
+    }
+
+
+    private int getMax1(Collection<Integer> col, Comparator c) {
+        assert(!col.isEmpty());
+        Iterator<Integer> it = col.iterator();
+        int max = it.next();
+        while(it.hasNext()) {
+            int next = it.next();
+            if (c.compare(max, next) < 0) max = next;
+        }
+        return max;
+    }
+
+    private int getMax2(Collection<Integer> col, Comparator c) {
+        assert (!col.isEmpty());
+        int any = col.iterator().next();
+        java.util.Optional<Integer> max = col.stream().reduce(LambdaUtilities.maxIntegerBinaryOperator(c));
+        assert(max.isPresent());
+        return max.get();
+    }
+
+    private int getMax3(Collection<Integer> col, Comparator c) {
+        assert (!col.isEmpty());
+        Integer any = col.iterator().next();
+        int max = col.stream().reduce(any, LambdaUtilities.maxIntegerFunction(c),
+                LambdaUtilities.maxIntegerBinaryOperator(c));
+        return max;
+    }
+
+    private int getMax4(Collection<Integer> col, Comparator c) {
+        assert (!col.isEmpty());
+        AtomicInteger max = col.stream().collect(LambdaUtilities.atomicIntegerSupplier(0),
+                    LambdaUtilities.maxIntegerBiConsumer(c),
+                    LambdaUtilities.maxAtomicIntegerBiConsumer(c));
+        return max.get();
+    }
+
+    /*
+     * c could be reversed order, we can't use MAX_VALUE or MIN_VALUE but we can
+     * use 1st element to compare with.
+     */
+    private int getMin1(Collection<Integer> col, Comparator c) {
+        assert(!col.isEmpty());
+        Iterator<Integer> it = col.iterator();
+        int min = it.next();
+        while(it.hasNext()) {
+            int next = it.next();
+            if (c.compare(min, next) > 0) min = next;
+        }
+        return min;
+    }
+
+    private int getMin2(Collection<Integer> col, Comparator c) {
+        assert (!col.isEmpty());
+        int any = col.iterator().next();
+        java.util.Optional<Integer> min = col.stream().reduce(LambdaUtilities.minIntegerBinaryOperator(c));
+        assert(min.isPresent());
+        return min.get();
+    }
+
+    private int getMin3(Collection<Integer> col, Comparator c) {
+        assert (!col.isEmpty());
+        Integer any = col.iterator().next();
+        int min = col.stream().reduce(any, LambdaUtilities.minIntegerFunction(c),
+                LambdaUtilities.minIntegerBinaryOperator(c));
+        return min;
+    }
+
+    private int getMin4(Collection<Integer> col, Comparator c) {
+        assert (!col.isEmpty());
+        AtomicInteger min = col.stream().collect(LambdaUtilities.atomicIntegerSupplier(0),
+                    LambdaUtilities.minIntegerBiConsumer(c),
+                    LambdaUtilities.minAtomicIntegerBiConsumer(c));
+        return min.get();
+    }
+
+    private void verifySlice(Iterator<Integer> itOrg, Iterator<Integer> itSliced,
+            int skip, int limit) {
+        int pos = 0;
+        while(itOrg.hasNext() && pos++ < skip)
+            itOrg.next();
+
+        while(itOrg.hasNext() && pos++ < limit)
+            assertEquals(itOrg.next(), itSliced.next());
+
+    }
+
+    private void verifyAfterOps(Iterator<Integer> itOrg, PrimitiveIterator<Integer> pit, LambdaUtilities.IntOp op,
+            int value) {
+        while(itOrg.hasNext() && pit.hasNext()) {
+            int expected = itOrg.next();
+            if(value != 0) {
+                switch (op) {
+                    case ADD:
+                        expected += value;
+                        break;
+                    case SUBTRACT:
+                        expected -= value;
+                        break;
+                    case MULTIPLY:
+                        expected *= value;
+                        break;
+                    case DIVIDE:
+                        expected /= value;
+                        break;
+                    default:
+                        expected %= value;
+                        break;
+                }
+            }
+            assertEquals(expected, pit.nextInt());
+        }
+        assertEquals(itOrg.hasNext(), pit.hasNext());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/stream/Stream/StringBuilderStreamTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,955 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary
+ * @library ../..
+ * @(#) StringBuilderStreamTest.java
+ * @author Eric Wang/Tristan Yan
+ * @run testng StringBuilderStreamTest
+ */
+
+import java.util.*;
+import java.util.concurrent.*;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiFunction;
+import java.util.function.Predicate;
+import java.util.function.Predicates;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import java.util.stream.Streams;
+import static org.testng.Assert.*;
+import org.testng.ITest;
+import org.testng.annotations.*;
+
+public class StringBuilderStreamTest<T extends Collection<StringBuilder>> implements ITest {
+    private final static int MIN_LEN = 1 << 2;
+
+    private final static int MAX_LEN = 1 << 12;
+
+    private final static int DATA_SIZE = 1 << 10;
+
+    private final static Random rand = new Random(System.currentTimeMillis());
+
+    private final static Comparator<StringBuilder> NATRUAL_ORDER_CMP = (sb1 ,sb2) -> sb1.toString().compareTo(sb2.toString());
+
+    private final static Comparator[] cmps = {NATRUAL_ORDER_CMP, NATRUAL_ORDER_CMP.reverseOrder()};
+
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    protected static Class[] defaultConstructorClazz = {
+        (Class<ArrayDeque<StringBuilder>>)(Class<?>)(ArrayDeque.class),
+        (Class<ArrayList<StringBuilder>>)(Class<?>)(ArrayList.class),
+        (Class<ConcurrentLinkedDeque<StringBuilder>>)(Class<?>)(ConcurrentLinkedDeque.class),
+        (Class<ConcurrentLinkedQueue<StringBuilder>>)(Class<?>)(ConcurrentLinkedQueue.class),
+//        (Class<ConcurrentSkipListSet<StringBuilder>>)(Class<?>)(ConcurrentSkipListSet.class),
+        (Class<CopyOnWriteArrayList<StringBuilder>>)(Class<?>)(CopyOnWriteArrayList.class),
+        (Class<HashSet<StringBuilder>>)(Class<?>)(HashSet.class),
+        (Class<LinkedBlockingDeque<StringBuilder>>)(Class<?>)(LinkedBlockingDeque.class),
+        (Class<LinkedBlockingQueue<StringBuilder>>)(Class<?>)(LinkedBlockingQueue.class),
+        (Class<LinkedHashSet<StringBuilder>>)(Class<?>)(LinkedHashSet.class),
+        (Class<LinkedList<StringBuilder>>)(Class<?>)(LinkedList.class),
+        (Class<LinkedTransferQueue<StringBuilder>>)(Class<?>)(LinkedTransferQueue.class),
+//        (Class<PriorityBlockingQueue<StringBuilder>>)(Class<?>)(PriorityBlockingQueue.class),
+//        (Class<PriorityQueue<StringBuilder>>)(Class<?>)(PriorityQueue.class),
+        (Class<Stack<StringBuilder>>)(Class<?>)(Stack.class),
+//        (Class<TreeSet<StringBuilder>>)(Class<?>)(TreeSet.class),
+        (Class<Vector<StringBuilder>>)(Class<?>)(Vector.class)
+    };
+
+    enum ParallelType { Parallel, Sequential, Default};
+
+    protected Class<T> typeObject;
+
+    protected boolean hasIni;
+
+    protected int initSize;
+
+    public StringBuilderStreamTest(Class<T> clazz, int... initSizes) {
+        this.typeObject = clazz;
+        assert(initSizes.length <= 1);
+        if(initSizes.length == 1) {
+            hasIni = true;
+            this.initSize = initSizes[0];
+        }
+    }
+
+    @Factory
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public static Object[] create(){
+        List<StringBuilderStreamTest> result = new ArrayList<>();
+        Stream<Class> stream1 = Arrays.stream(defaultConstructorClazz);
+        stream1.forEach(clazz -> result.add(new StringBuilderStreamTest(clazz)));
+        return result.toArray();
+    }
+
+    @Override
+    public String getTestName() {
+        return typeObject.getName() + "<StringBuilder>";
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testAllMatch() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<StringBuilder> c1 =  generateData(DATA_SIZE);
+            Stream<StringBuilder> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream():
+                    (type == ParallelType.Sequential) ? c1.parallelStream().sequential() :
+                    c1.stream();
+            EnumSet<LambdaUtilities.CharType> set = EnumSet.allOf(LambdaUtilities.CharType.class);
+            LambdaUtilities.CharType charType
+                    = (LambdaUtilities.CharType)set.toArray()[rand.nextInt(4)];
+            boolean isFirst = rand.nextBoolean();
+            assertEquals(stream1.allMatch((Predicate<StringBuilder>)LambdaUtilities.randomSBPredicate(charType, isFirst)),
+                    verifyMatch(c1, charType, isFirst, true));
+
+            //Empty stream's allMatch  will return true always
+            @SuppressWarnings("cast")
+            Collection<StringBuilder> emptyCol =  hasIni ?
+                    (Collection<StringBuilder>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<StringBuilder>)LambdaUtilities.create(typeObject);
+            Stream<StringBuilder> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.parallelStream().sequential() :
+                    emptyCol.stream();
+            assertTrue(stream2.allMatch((Predicate<StringBuilder>)LambdaUtilities.randomSBPredicate(charType, isFirst)));
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testAnyMatch() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<StringBuilder> c1 =  generateData(DATA_SIZE);
+            Stream<StringBuilder> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream():
+                    (type == ParallelType.Sequential) ? c1.parallelStream().sequential() :
+                    c1.stream();
+            EnumSet<LambdaUtilities.CharType> set = EnumSet.allOf(LambdaUtilities.CharType.class);
+            LambdaUtilities.CharType charType
+                    = (LambdaUtilities.CharType)set.toArray()[rand.nextInt(4)];
+            boolean isFirst = rand.nextBoolean();
+            assertEquals(stream1.anyMatch((Predicate<StringBuilder>)LambdaUtilities.randomSBPredicate(charType, isFirst)),
+                    verifyMatch(c1, charType, isFirst, false));
+
+            //Empty stream's anyMatch  will return false always
+            @SuppressWarnings("cast")
+            Collection<StringBuilder> emptyCol =  hasIni ?
+                    (Collection<StringBuilder>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<StringBuilder>)LambdaUtilities.create(typeObject);
+            Stream<StringBuilder> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.parallelStream().sequential() :
+                    emptyCol.stream();
+            assertTrue(!stream2.anyMatch((Predicate<StringBuilder>)LambdaUtilities.randomSBPredicate(charType, isFirst)));
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testConcat() throws Exception{
+                Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            //Concate two list's stream, then filter one predicate should be expect
+            //to be same as filter two stream repectively then concate the result.
+            Collection<StringBuilder> l1 =  generateData(DATA_SIZE);
+            Collection<StringBuilder> l2 =  generateData(DATA_SIZE);
+             EnumSet<LambdaUtilities.CharType> set = EnumSet.allOf(LambdaUtilities.CharType.class);
+             LambdaUtilities.CharType charType
+                    = (LambdaUtilities.CharType)set.toArray()[rand.nextInt(4)];
+            boolean isFirst = rand.nextBoolean();
+            Predicate<StringBuilder> p = (Predicate<StringBuilder>)LambdaUtilities.randomSBPredicate(charType, isFirst);
+
+            Stream<StringBuilder> stream11 = (type == ParallelType.Parallel) ? l1.parallelStream():
+                    (type == ParallelType.Sequential) ? l1.parallelStream().sequential() :
+                    l1.stream();
+            Stream<StringBuilder> stream21 = (type == ParallelType.Parallel) ? l2.parallelStream():
+                    (type == ParallelType.Sequential) ? l2.parallelStream().sequential() :
+                    l2.stream();
+            Collection<StringBuilder> result1 = stream11.filter(p).collect(Collectors.toCollection(LinkedList<StringBuilder>::new));
+            Collection<StringBuilder> result2 = stream21.filter(p).collect(Collectors.toCollection(LinkedList<StringBuilder>::new));
+            result1.addAll(result2);
+
+            Stream<StringBuilder> stream12 = (type == ParallelType.Parallel) ? l1.parallelStream():
+                    (type == ParallelType.Sequential) ? l1.parallelStream().sequential() :
+                    l1.stream();
+            Stream<StringBuilder> stream22 = (type == ParallelType.Parallel) ? l2.parallelStream():
+                    (type == ParallelType.Sequential) ? l2.parallelStream().sequential() :
+                    l2.stream();
+            List<String> expectedList = Streams.concat(stream12, stream22).filter(p).map(t -> t.toString()).collect(Collectors.<String>toList());
+            List<String> testList = result1.stream().map(t -> t.toString()).collect(Collectors.<String>toList());
+
+            Collections.sort(testList);
+            Collections.sort(expectedList);
+            assertEquals(testList, expectedList);
+
+            Collection<StringBuilder> emptyList = hasIni ? LambdaUtilities.create(typeObject, initSize)
+                : LambdaUtilities.create(typeObject);
+            Stream<StringBuilder> stream3 = (type == ParallelType.Parallel) ? emptyList.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyList.parallelStream().sequential() :
+                    emptyList.stream();
+            List<StringBuilder> result3 = Streams.concat(l1.stream(), stream3).collect(Collectors.<StringBuilder>toList());
+            List<StringBuilder> list1 = new ArrayList<StringBuilder>(l1);
+            Collections.sort(list1, NATRUAL_ORDER_CMP);
+            Collections.sort(result3, NATRUAL_ORDER_CMP);
+            assertEquals(list1, result3);
+        }
+    }
+
+    @Test
+    public void testFind() throws Throwable {
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<StringBuilder> c =  generateData(DATA_SIZE);
+            Stream<StringBuilder> stream1 = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+            Stream<StringBuilder> stream2 = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+            java.util.Optional<StringBuilder> opAny = stream1.findAny();
+            java.util.Optional<StringBuilder> opFirst = stream2.findFirst();
+            assertTrue(opAny.isPresent());
+            assertTrue(opFirst.isPresent());
+            if(!stream1.isParallel())
+                assertEquals(opAny, opFirst);
+            @SuppressWarnings("cast")
+            Collection<StringBuilder> emptyCol =  hasIni ?
+                    (Collection<StringBuilder>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<StringBuilder>)LambdaUtilities.create(typeObject);
+            Stream<StringBuilder> emptyStream1 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                    emptyCol.stream();
+            java.util.Optional<StringBuilder> emptyAny = emptyStream1.findAny();
+            assertFalse(emptyAny.isPresent());
+            Stream<StringBuilder> emptyStream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.stream().sequential() :
+                    emptyCol.stream();
+            java.util.Optional<StringBuilder> emptyFirsty = emptyStream2.findFirst();
+            assertFalse(emptyFirsty.isPresent());
+        }
+    }
+
+    @Test
+    public void testForEach() throws Throwable {
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<StringBuilder> c =  generateData(DATA_SIZE);
+            Stream<StringBuilder> stream = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.parallelStream().sequential() :
+                    c.stream();
+            stream.forEach(t -> { assertTrue(c.contains(t)); });
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testFilter() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            //Create predicate with random limit and random up/down size
+            Collection<StringBuilder> l =  generateData(DATA_SIZE);
+            Stream<StringBuilder> stream = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+
+            EnumSet<LambdaUtilities.CharType> set = EnumSet.allOf(LambdaUtilities.CharType.class);
+            LambdaUtilities.CharType charType
+                    = (LambdaUtilities.CharType)set.toArray()[rand.nextInt(4)];
+            boolean isFirst = rand.nextBoolean();
+            Predicate<StringBuilder> p1 = (Predicate<StringBuilder>)LambdaUtilities.randomSBPredicate(charType, isFirst);
+            //Filter the data, check if it works as expected.
+            Collection<StringBuilder> result1 = stream.filter(p1).collect(Collectors.toCollection(LinkedList<StringBuilder>::new));
+            assertTrue(verifyMatch(result1, charType, isFirst, true));
+            //filter on parallel stream can cause IllegalStateException
+            stream = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+            result1.clear();
+            result1 = stream.filter(p1).filter(Predicates.alwaysTrue()).collect(Collectors.toCollection(LinkedList<StringBuilder>::new));
+            assertTrue(verifyMatch(result1, charType, isFirst, true));
+
+            //filter with Predicates.alwaysFlase() will get nothing
+            stream = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+            result1.clear();
+            result1 = stream.filter(p1).filter(Predicates.alwaysFalse()).collect(Collectors.toCollection(LinkedList<StringBuilder>::new));
+            assertEquals(result1.size(), 0);
+
+            EnumSet<LambdaUtilities.CharType> set2 = EnumSet.allOf(LambdaUtilities.CharType.class);
+            LambdaUtilities.CharType charType2
+                    = (LambdaUtilities.CharType)set2.toArray()[rand.nextInt(4)];
+            boolean isFirst2 = rand.nextBoolean();
+            Predicate<StringBuilder> p2 = (Predicate<StringBuilder>)LambdaUtilities.randomSBPredicate(charType2, isFirst2);
+
+            EnumSet<LambdaUtilities.CharType> set3 = EnumSet.allOf(LambdaUtilities.CharType.class);
+            LambdaUtilities.CharType charType3
+                    = (LambdaUtilities.CharType)set3.toArray()[rand.nextInt(4)];
+            boolean isFirst3 = rand.nextBoolean();
+            Predicate<StringBuilder> p3 = (Predicate<StringBuilder>)LambdaUtilities.randomSBPredicate(charType3, isFirst3);
+            //The reason conver l to sorted is CopyOnWriteArrayList doesn't support
+            //sort, we use ArrayList sort data instead
+            stream = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+            List<StringBuilder> result2 = stream.filter(p1).filter(p2).collect(Collectors.<StringBuilder>toList());
+            stream = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+            List<StringBuilder> result3 = stream.filter(Predicates.and(p1,p2)).collect(Collectors.<StringBuilder>toList());
+            Collections.sort(result2, (sb1 ,sb2) -> sb1.toString().compareTo(sb2.toString()));
+            Collections.sort(result3, (sb1 ,sb2) -> sb1.toString().compareTo(sb2.toString()));
+            assertEquals(result2, result3);
+            result2.clear();
+            result3.clear();
+
+            stream = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+            result2 = stream.filter(Predicates.and(p1,p2)).collect(Collectors.<StringBuilder>toList());
+            stream = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+            result3 = stream.filter(Predicates.or(p1,p2)).collect(Collectors.<StringBuilder>toList());
+            result2.addAll(result3);
+            result3.clear();
+            stream = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+            Stream<StringBuilder>  stream2 = (type == ParallelType.Parallel) ? l.parallelStream():
+                    ((type == ParallelType.Sequential) ? l.stream().sequential() :
+                    l.stream());
+            result3 = Streams.concat(stream.filter(p1), stream2.filter(p2)).collect(Collectors.<StringBuilder>toList());
+            Collections.sort(result2, NATRUAL_ORDER_CMP);
+            Collections.sort(result3, NATRUAL_ORDER_CMP);
+            assertEquals(result2, result3);
+
+            @SuppressWarnings("cast")
+            Collection<StringBuilder> emptyList  =  hasIni ?
+                    (Collection<StringBuilder>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<StringBuilder>)LambdaUtilities.create(typeObject);
+            Stream<StringBuilder> stream3 = (type == ParallelType.Parallel) ? emptyList.parallelStream():
+                (type == ParallelType.Sequential) ? emptyList.parallelStream().sequential() :
+                emptyList.stream();
+            assertFalse(stream3.filter(p1).iterator().hasNext());
+        }
+    }
+
+    @Test
+    protected void testLimit() throws Throwable {
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<StringBuilder> c =  generateData(DATA_SIZE / 10);
+            int limit = rand.nextInt(DATA_SIZE / 10 * 2);
+            Stream<StringBuilder> stream1 = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+            Collection<StringBuilder> result1  = stream1.explode(LambdaUtilities.genSBFlatBiConsumer(2, DATA_SIZE / 10)).collect(Collectors.toCollection(LinkedList<StringBuilder>::new));
+
+            Stream<StringBuilder> stream2 = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+            Collection<StringBuilder> result2 = stream2.explode(LambdaUtilities.genSBFlatBiConsumer(2, DATA_SIZE / 10)).limit(limit).collect(Collectors.toCollection(LinkedList<StringBuilder>::new));
+
+            if(limit > result1.size())
+                assertTrue(result1.size() == result2.size());
+            else {
+                assertTrue(result2.size() == limit);
+            }
+        }
+    }
+
+    @Test
+    public void testExplode() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<StringBuilder> c =  generateData(DATA_SIZE / 10);
+            int selected = rand.nextInt(4);
+            Stream<StringBuilder> stream = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+            List<StringBuilder> result = stream.explode(LambdaUtilities.genSBFlatBiConsumer(selected, DATA_SIZE / 10)).collect(Collectors.<StringBuilder>toList());
+            verifyFlatBiBlock(c, result, selected, DATA_SIZE / 10);
+        }
+    }
+
+    @Test
+    @SuppressWarnings({"unchecked","rawtypes"})
+    public void testMax() throws Exception{
+        for (Comparator comp  : cmps) {
+            Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+            while (iter.hasNext()) {
+                ParallelType type = iter.next();
+                Collection<StringBuilder> col1 = generateData(DATA_SIZE);
+                Stream<StringBuilder> stream1 = (type == ParallelType.Parallel) ? col1.parallelStream()
+                        : (type == ParallelType.Sequential) ? col1.parallelStream().sequential()
+                        : col1.stream();
+                java.util.Optional<StringBuilder> optional = stream1.max(comp);
+                assertTrue(optional.isPresent());
+                assertEquals(optional.get(), getMax(col1, comp));
+                assertEquals(optional.get(), getMax1(col1, comp));
+                assertEquals(optional.get(), getMax2(col1, comp));
+
+                @SuppressWarnings("cast")
+                Collection<StringBuilder> emptyCol = hasIni
+                        ? (Collection<StringBuilder>) LambdaUtilities.create(typeObject, initSize)
+                        : (Collection<StringBuilder>) LambdaUtilities.create(typeObject);
+                Stream<StringBuilder> emptyStream = (type == ParallelType.Parallel) ? emptyCol.parallelStream()
+                        : (type == ParallelType.Sequential) ? emptyCol.stream().sequential()
+                        : emptyCol.stream();
+                assertFalse(emptyStream.max(comp).isPresent());
+            }
+        }
+    }
+
+    @Test
+    @SuppressWarnings({"unchecked","rawtypes"})
+    public void testMin() throws Exception{
+        for (Comparator comp  : cmps) {
+            Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+            while (iter.hasNext()) {
+                ParallelType type = iter.next();
+                Collection<StringBuilder> col1 = generateData(DATA_SIZE);
+                Stream<StringBuilder> stream1 = (type == ParallelType.Parallel) ? col1.parallelStream()
+                        : (type == ParallelType.Sequential) ? col1.parallelStream().sequential()
+                        : col1.stream();
+                java.util.Optional<StringBuilder> optional = stream1.min(comp);
+                assertTrue(optional.isPresent());
+                assertEquals(optional.get(), getMin(col1, comp));
+                assertEquals(optional.get(), getMin1(col1, comp));
+                assertEquals(optional.get(), getMin2(col1, comp));
+
+                @SuppressWarnings("cast")
+                Collection<StringBuilder> emptyCol = hasIni
+                        ? (Collection<StringBuilder>) LambdaUtilities.create(typeObject, initSize)
+                        : (Collection<StringBuilder>) LambdaUtilities.create(typeObject);
+                Stream<StringBuilder> emptyStream = (type == ParallelType.Parallel) ? emptyCol.parallelStream()
+                        : (type == ParallelType.Sequential) ? emptyCol.stream().sequential()
+                        : emptyCol.stream();
+                assertFalse(emptyStream.min(comp).isPresent());
+            }
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testNoneMatch() throws Exception{
+       Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<StringBuilder> c1 =  generateData(DATA_SIZE);
+            Stream<StringBuilder> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream():
+                    (type == ParallelType.Sequential) ? c1.parallelStream().sequential() :
+                    c1.stream();
+            EnumSet<LambdaUtilities.CharType> set = EnumSet.allOf(LambdaUtilities.CharType.class);
+            LambdaUtilities.CharType charType
+                    = (LambdaUtilities.CharType)set.toArray()[rand.nextInt(4)];
+            boolean isFirst = rand.nextBoolean();
+            assertTrue(stream1.noneMatch((Predicate<StringBuilder>)LambdaUtilities.randomSBPredicate(charType, isFirst)) ==
+                    verifyMatch(c1, charType, !isFirst, true));
+
+            //Empty stream's noneMatch will return true always
+            @SuppressWarnings("cast")
+            Collection<StringBuilder> emptyCol =  hasIni ?
+                    (Collection<StringBuilder>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<StringBuilder>)LambdaUtilities.create(typeObject);
+            Stream<StringBuilder> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.parallelStream().sequential() :
+                    emptyCol.stream();
+            assertTrue(stream2.noneMatch((Predicate<StringBuilder>)LambdaUtilities.randomSBPredicate(charType, !isFirst)));
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testReduceWithoutBase() throws Exception {
+        Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+        while (iter.hasNext()) {
+            ParallelType type = iter.next();
+            // Can't predict Parallel Add/Substract reduce result, give up
+            // testing on parallel substract test
+            if (type == ParallelType.Parallel)
+                continue;
+            Collection<StringBuilder> col1 = generateData(DATA_SIZE / 10);
+            Stream<StringBuilder> streamPlus = (type == ParallelType.Parallel) ? col1.parallelStream()
+                    : (type == ParallelType.Sequential) ? col1.stream().sequential() : col1.stream();
+            java.util.Optional<StringBuilder> oiPlus = streamPlus.reduce(LambdaUtilities.appendSBBinaryOperator());
+            assertTrue(oiPlus.isPresent());
+            StringBuilder total = new StringBuilder();
+            Iterator<StringBuilder> it1 = col1.iterator();
+            while (it1.hasNext())
+                total.append(it1.next());
+            assertEquals(oiPlus.get().toString(), total.toString());
+            ArrayList<StringBuilder> list1 = new ArrayList<>(col1);
+            list1.add(0, total);
+            Stream<StringBuilder> streamSubtract = (type == ParallelType.Parallel) ? list1.parallelStream()
+                    : (type == ParallelType.Sequential) ? list1.stream().sequential() : list1.stream();
+            java.util.Optional<StringBuilder> oiSubtract = streamSubtract.reduce(LambdaUtilities
+                    .deleteSBBinaryOperator());
+            assertTrue(oiSubtract.isPresent());
+
+            Iterator<StringBuilder> it2 = list1.iterator();
+            StringBuilder subTotal = it2.next();
+            while (it2.hasNext()) {
+                String s = it2.next().toString();
+                int i1 = subTotal.indexOf(s);
+                int i2 = i1 + s.length();
+                subTotal.delete(i1, i2);
+            }
+            assertEquals(oiSubtract.get().toString(), subTotal.toString());
+
+            @SuppressWarnings("cast")
+            Collection<StringBuilder> emptyCol = hasIni ? (Collection<StringBuilder>) LambdaUtilities.create(
+                    typeObject, initSize) : (Collection<StringBuilder>) LambdaUtilities.create(typeObject);
+            Stream<StringBuilder> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream()
+                    : (type == ParallelType.Sequential) ? emptyCol.stream().sequential() : emptyCol.stream();
+            java.util.Optional<StringBuilder> emptyOp = stream2.reduce(rand.nextBoolean() ? LambdaUtilities
+                    .appendSBBinaryOperator() : LambdaUtilities.deleteSBBinaryOperator());
+            assertFalse(emptyOp.isPresent());
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testReduceWithBase() throws Exception {
+        Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+        while (iter.hasNext()) {
+            ParallelType type = iter.next();
+            // Can't predict Parallel Add/Substract reduce result, give up
+            // testing on parallel substract test
+            if (type == ParallelType.Parallel)
+                continue;
+            Collection<StringBuilder> col1 = generateData(DATA_SIZE / 10);
+
+            StringBuilder base = (StringBuilder) col1.toArray()[rand.nextInt(col1.size())];
+            StringBuilder total = new StringBuilder(base.toString());
+
+            Stream<StringBuilder> streamPlus = (type == ParallelType.Parallel) ? col1.parallelStream()
+                    : (type == ParallelType.Sequential) ? col1.stream().sequential() : col1.stream();
+            StringBuilder oiPlus = streamPlus.reduce(base, LambdaUtilities.appendSBBinaryOperator());
+
+            Iterator<StringBuilder> it1 = col1.iterator();
+            while (it1.hasNext())
+                total.append(it1.next());
+            assertEquals(oiPlus.toString(), total.toString());
+
+            ArrayList<StringBuilder> list1 = new ArrayList<>(col1);
+            list1.add(0, total);
+
+            Stream<StringBuilder> streamSubtract = (type == ParallelType.Parallel) ? list1.parallelStream()
+                    : (type == ParallelType.Sequential) ? list1.stream().sequential() : list1.stream();
+            StringBuilder oiSub = streamSubtract.reduce(base, LambdaUtilities.deleteSBBinaryOperator());
+
+            StringBuilder subTotal = total.delete(0, base.length());
+            Iterator<StringBuilder> it2 = col1.iterator();
+            while (it2.hasNext()) {
+                String s = it2.next().toString();
+                int i1 = subTotal.indexOf(s);
+                int i2 = i1 + s.length();
+                subTotal.delete(i1, i2);
+            }
+
+            assertEquals(subTotal.toString(), oiSub.toString());
+
+            @SuppressWarnings("cast")
+            Collection<StringBuilder> emptyCol = hasIni ? (Collection<StringBuilder>) LambdaUtilities.create(
+                    typeObject, initSize) : (Collection<StringBuilder>) LambdaUtilities.create(typeObject);
+            Stream<StringBuilder> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream()
+                    : (type == ParallelType.Sequential) ? emptyCol.stream().sequential() : emptyCol.stream();
+            StringBuilder emptyOp = stream2.reduce(base, rand.nextBoolean() ? LambdaUtilities.appendSBBinaryOperator()
+                    : LambdaUtilities.deleteSBBinaryOperator());
+            assertEquals(emptyOp, base);
+        }
+    }
+
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testSubstream() throws Exception {
+        Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+        BiFunction<Integer, Integer, Integer> bf = LambdaUtilities.randBetweenIntegerFunction();
+        while (iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<StringBuilder> col = generateData(DATA_SIZE);
+            int skip = rand.nextInt(col.size());
+            // limit has more than 50% chance less than col.size() - skip
+            int limit = rand.nextBoolean() ? bf.apply(0, col.size() - skip) : rand.nextInt(Integer.MAX_VALUE);
+            Stream<StringBuilder> stream1 = (type == ParallelType.Parallel) ? col.parallelStream()
+                    : (type == ParallelType.Sequential) ? col.stream().sequential() : col.stream();
+            Iterator<StringBuilder> it = stream1.substream(skip, skip + limit).iterator();
+            verifySlice(col.iterator(), it, skip, limit);
+
+            // limit=0 causes empty stream
+            Stream<StringBuilder> stream2 = (type == ParallelType.Parallel) ? col.parallelStream()
+                    : (type == ParallelType.Sequential) ? col.stream().sequential() : col.stream();
+            assertFalse(stream2.substream(skip, skip).iterator().hasNext());
+
+            // skip exceed collection size cause empty stream
+            Stream<StringBuilder> stream3 = (type == ParallelType.Parallel) ? col.parallelStream()
+                    : (type == ParallelType.Sequential) ? col.stream().sequential() : col.stream();
+            int skipExceeded = bf.apply(col.size(), Integer.MAX_VALUE);
+            assertFalse(stream3.substream(skipExceeded, skipExceeded + 1).iterator().hasNext());
+
+            @SuppressWarnings("cast")
+            Collection<StringBuilder> emptyCol = hasIni ? (Collection<StringBuilder>) LambdaUtilities.create(
+                    typeObject, initSize) : (Collection<StringBuilder>) LambdaUtilities.create(typeObject);
+            Stream<StringBuilder> emptyStream = (type == ParallelType.Parallel) ? emptyCol.parallelStream()
+                    : (type == ParallelType.Sequential) ? emptyCol.stream().sequential() : emptyCol.stream();
+            assertFalse(emptyStream.substream(skip, skip + limit).iterator().hasNext());
+        }
+    }
+
+    @Test
+    public void testSorted() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<StringBuilder> col =  generateData(DATA_SIZE);
+            Stream<StringBuilder> stream = (type == ParallelType.Parallel) ? col.parallelStream():
+                    (type == ParallelType.Sequential) ? col.parallelStream().sequential() :
+                    col.stream();
+            List<StringBuilder> reversed = stream.sorted(NATRUAL_ORDER_CMP.reverseOrder()).collect(Collectors.<StringBuilder>toList());
+            //The reason conver l to sorted is CopyOnWriteArrayList doesn't support
+            //sort, we use ArrayList sort data instead
+            List<StringBuilder> sorted = new ArrayList<>(col);
+            Collections.sort(sorted, NATRUAL_ORDER_CMP);
+
+            //SortedSet instance's stream can't be reordered
+            if(!(col instanceof SortedSet))
+                Collections.sort(sorted, NATRUAL_ORDER_CMP.reverseOrder());
+            assertEquals(sorted, reversed);
+
+            @SuppressWarnings("cast")
+            Collection<StringBuilder> emptyCol  = hasIni ?
+                    (Collection<StringBuilder>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<StringBuilder>)LambdaUtilities.create(typeObject);
+            Stream<StringBuilder> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                (type == ParallelType.Sequential) ? emptyCol.parallelStream().sequential() :
+                emptyCol.stream();
+            assertFalse(stream2.sorted(NATRUAL_ORDER_CMP.reverseOrder()).iterator().hasNext());
+        }
+    }
+
+    @Test
+    public void testPeek() throws Exception {
+        Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+        while (iter.hasNext()) {
+            ParallelType type = iter.next();
+            if (type == ParallelType.Parallel) {
+                continue;
+            }
+            Collection<StringBuilder> c1 = generateData(DATA_SIZE / 10);
+            Stream<StringBuilder> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream()
+                    : (type == ParallelType.Sequential) ? c1.stream().sequential() : c1.stream();
+            Stream<StringBuilder> stream2 = (type == ParallelType.Parallel) ? c1.parallelStream()
+                    : (type == ParallelType.Sequential) ? c1.stream().sequential() : c1.stream();
+            StringBuilder sb1 = new StringBuilder();
+            Iterator<StringBuilder> it = stream1.peek(LambdaUtilities.appendSBConsumer(sb1)).iterator();
+            StringBuilder expectedTotal = new StringBuilder();
+            while (it.hasNext())
+                expectedTotal.append(it.next());
+            assertEquals(sb1.toString(), expectedTotal.toString());
+            AtomicReference<StringBuilder> sb2 = stream2.collect(
+                    LambdaUtilities.atomicSBSupplier(new StringBuilder()), LambdaUtilities.appendSBBiConsumer(),
+                    LambdaUtilities.appendAtomicSBBiConsumer());
+            assertEquals(sb2.get().toString(), expectedTotal.toString());
+
+            @SuppressWarnings("cast")
+            Collection<StringBuilder> emptyCol = hasIni ? (Collection<StringBuilder>) LambdaUtilities.create(
+                    typeObject, initSize) : (Collection<StringBuilder>) LambdaUtilities.create(typeObject);
+            Stream<StringBuilder> emptyStream = (type == ParallelType.Parallel) ? emptyCol.parallelStream()
+                    : (type == ParallelType.Sequential) ? emptyCol.stream().sequential() : emptyCol.stream();
+            assertFalse(emptyStream.peek(LambdaUtilities.appendSBConsumer(sb1)).iterator().hasNext());
+            assertEquals(sb1.toString(), expectedTotal.toString());
+        }
+    }
+
+    @Test
+    public void testToArray() throws Exception{
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<StringBuilder> c1 =  generateData(DATA_SIZE);
+            Stream<StringBuilder> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream():
+                    (type == ParallelType.Sequential) ? c1.parallelStream().sequential() :
+                    c1.stream();
+            Object[] arr1 = stream1.toArray();
+            Object[] arr2 = c1.toArray();
+            assertEquals(arr1, arr2);
+
+            @SuppressWarnings("cast")
+            Collection<StringBuilder> emptyCol =  hasIni ?
+                    (Collection<StringBuilder>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<StringBuilder>)LambdaUtilities.create(typeObject);
+            Stream<StringBuilder> stream2 = (type == ParallelType.Parallel) ? emptyCol.parallelStream():
+                    (type == ParallelType.Sequential) ? emptyCol.parallelStream().sequential() :
+                    emptyCol.stream();
+            assertEquals(stream2.toArray().length, 0);
+        }
+    }
+
+    @Test
+    public void testUniqueElements() throws Exception {
+        Iterator<ParallelType> iter = EnumSet.allOf(ParallelType.class).iterator();
+        while (iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<StringBuilder> c1 = generateData(DATA_SIZE / 10);
+            Set<StringBuilder> set1 = new HashSet<>(c1);
+            Stream<StringBuilder> stream1 = (type == ParallelType.Parallel) ? c1.parallelStream()
+                    : (type == ParallelType.Sequential) ? c1.stream().sequential() : c1.stream();
+             List<StringBuilder> list2 = stream1.explode(LambdaUtilities.genSBFlatBiConsumer(3, DATA_SIZE / 10)).distinct().collect(Collectors.<StringBuilder>toList());
+            assertEquals(set1.size(), list2.size());
+            assertTrue(set1.containsAll(list2));
+        }
+    }
+
+    @Test
+    public void testGroupBy() throws Throwable {
+        Iterator<ParallelType> iter
+                = EnumSet.allOf(ParallelType.class).iterator();
+        while(iter.hasNext()) {
+            ParallelType type = iter.next();
+            Collection<StringBuilder> c =  generateData(DATA_SIZE);
+
+            boolean isFirst = rand.nextBoolean();
+            Stream<StringBuilder> stream = (type == ParallelType.Parallel) ? c.parallelStream():
+                    (type == ParallelType.Sequential) ? c.stream().sequential() :
+                    c.stream();
+            Map<LambdaUtilities.CharType, Collection<StringBuilder>> result
+                    = stream.collect(Collectors.groupingBy(LambdaUtilities.sbGenericFunction(isFirst)));
+            verifyGroupBy(result, isFirst);
+
+            @SuppressWarnings("cast")
+            Collection<StringBuilder> emptyList = hasIni ?
+                    (Collection<StringBuilder>)LambdaUtilities.create(typeObject, initSize) :
+                    (Collection<StringBuilder>)LambdaUtilities.create(typeObject);
+            Stream<StringBuilder> stream2 = (type == ParallelType.Parallel) ? emptyList.parallelStream():
+                (type == ParallelType.Sequential) ? emptyList.stream().sequential() :
+                emptyList.stream();
+            assertTrue(stream2.collect(Collectors.groupingBy(LambdaUtilities.sbGenericFunction(isFirst))).isEmpty());
+        }
+    }
+
+    protected Collection<StringBuilder> generateData(int n)
+            throws Exception{
+        Collection<StringBuilder> col = LambdaUtilities.create(typeObject);
+        for(int row=0; row < n; row++) {
+            col.add(new StringBuilder(StringUtilities.randomString(MAX_LEN, MIN_LEN)));
+        }
+        return col;
+    }
+
+    protected static boolean verifyMatch(Collection<StringBuilder> c,
+            LambdaUtilities.CharType charType, boolean isFirst, boolean all) {
+        Iterator<StringBuilder> it = c.iterator();
+        while(it.hasNext()) {
+            StringBuilder current = it.next();
+            char checkChar = current.charAt(isFirst ? 0 : current.toString().length() - 1);
+            switch(charType) {
+                case DIGIT:
+                    if(!all && Character.isDigit(checkChar))
+                        return true;
+                    else if (all && !Character.isDigit(checkChar)) {
+                        return false;
+                    }
+                    break;
+                case LOWERCASE:
+                    if(!all && Character.isLowerCase(checkChar))
+                        return true;
+                    else if (all && !Character.isLowerCase(checkChar)) {
+                        return false;
+                    }
+                    break;
+                case UPPERCASE:
+                    if(!all && Character.isUpperCase(checkChar))
+                        return true;
+                    else if (all && !Character.isUpperCase(checkChar)) {
+                        return false;
+                    }
+                    break;
+                default:
+                    if(!all && !Character.isLetterOrDigit(checkChar))
+                        return true;
+                    else if (all && Character.isLetterOrDigit(checkChar)) {
+                        return false;
+                    }
+                    break;
+            }
+        }
+        return all;
+    }
+
+   private void verifyGroupBy(Map<LambdaUtilities.CharType, Collection<StringBuilder>> result, boolean isFirst){
+        assertTrue(result.size() <= 4);
+        Iterator<LambdaUtilities.CharType> keyiter = result.keySet().iterator();
+        while(keyiter.hasNext()) {
+            LambdaUtilities.CharType key = keyiter.next();
+            Iterator<StringBuilder> valueiter = result.get(key).iterator();
+            while(valueiter.hasNext()) {
+                StringBuilder i = valueiter.next();
+                Character c = null;
+                if(isFirst)
+                    c = Character.valueOf(i.charAt(0));
+                else
+                    c = Character.valueOf(i.charAt(i.length() - 1));
+                LambdaUtilities.CharType t = Character.isAlphabetic(c) ?
+                    (Character.isUpperCase(c) ? LambdaUtilities.CharType.UPPERCASE : LambdaUtilities.CharType.LOWERCASE) :
+                    (Character.isDigit(c) ? LambdaUtilities.CharType.DIGIT : LambdaUtilities.CharType.SPECIAL);
+                assertTrue(t == key);
+             }
+        }
+    }
+
+    private void verifyFlatBiBlock(Collection<StringBuilder> orig, List<StringBuilder> result,
+            int selected, int unit) throws Exception{
+
+        switch(selected) {
+            case 0:
+                assertEquals(result.size(), 0);
+                break;
+            case 1:
+                List<StringBuilder> l1 = new ArrayList<>(orig);
+                Collections.sort(l1, NATRUAL_ORDER_CMP);
+                Collections.sort(result, NATRUAL_ORDER_CMP);
+                assertEquals(l1, result);
+                break;
+            case 2:
+                List<StringBuilder> l2 = new ArrayList<>();
+                Iterator<StringBuilder> it2 = orig.iterator();
+                while(it2.hasNext()) {
+                    StringBuilder current = it2.next();
+                    int step = current.length() / unit + unit -1;
+                    for (int i = 0; i < current.length(); i += step)
+                        l2.add(new StringBuilder(current.substring(i, i + step >= current.length() ?
+                               current.length() - 1 : i + step)));
+                }
+                Collections.sort(l2, NATRUAL_ORDER_CMP);
+                Collections.sort(result, NATRUAL_ORDER_CMP);
+                for (int j = 0; j < l2.size(); j ++) {
+                    StringBuilder s1 = l2.get(j);
+                    StringBuilder s2 = result.get(j);
+                    assertEquals(s1.toString(), s2.toString());
+                }
+                break;
+            case 3:
+                List<StringBuilder> l3 = new ArrayList<>();
+                Iterator<StringBuilder> it3 = orig.iterator();
+                while(it3.hasNext()) {
+                    StringBuilder current = it3.next();
+                    int step = current.length() / unit + unit -1;
+                    for(int i = 0; i < current.length(); i += step)
+                        l3.add(current);
+                }
+                Collections.sort(l3, NATRUAL_ORDER_CMP);
+                Collections.sort(result, NATRUAL_ORDER_CMP);
+                assertEquals(l3, result);
+                break;
+            default:
+                break;
+        }
+    }
+
+
+    private StringBuilder getMax(Collection<StringBuilder> col, Comparator<StringBuilder> c) {
+        assert(!col.isEmpty());
+        Iterator<StringBuilder> it = col.iterator();
+        StringBuilder max = it.next();
+        while(it.hasNext()) {
+            StringBuilder next = it.next();
+            if (c.compare(max, next) < 0) max = next;
+        }
+        return max;
+    }
+
+    private StringBuilder getMax1(Collection<StringBuilder> col, Comparator<StringBuilder> c) {
+        assert (!col.isEmpty());
+        StringBuilder any = col.iterator().next();
+        java.util.Optional<StringBuilder> max = col.stream().reduce(LambdaUtilities.maxSBBinaryOperator(c));
+        assert(max.isPresent());
+        return max.get();
+    }
+
+    private StringBuilder getMax2(Collection<StringBuilder> col, Comparator<StringBuilder> c) {
+        assert (!col.isEmpty());
+        StringBuilder any = col.iterator().next();
+        StringBuilder max = col.stream().reduce(any, LambdaUtilities.maxStringBuilderFunction(c),
+                LambdaUtilities.maxSBBinaryOperator(c));
+        return max;
+    }
+
+    private StringBuilder getMin(Collection<StringBuilder> col, Comparator<StringBuilder> c) {
+        assert(!col.isEmpty());
+        Iterator<StringBuilder> it = col.iterator();
+        StringBuilder min = it.next();
+        while(it.hasNext()) {
+            StringBuilder next = it.next();
+            if (c.compare(min, next) > 0) min = next;
+        }
+        return min;
+    }
+
+    private StringBuilder getMin1(Collection<StringBuilder> col, Comparator<StringBuilder> c) {
+        assert (!col.isEmpty());
+        StringBuilder any = col.iterator().next();
+        java.util.Optional<StringBuilder> min = col.stream().reduce(LambdaUtilities.minSBBinaryOperator(c));
+        assert(min.isPresent());
+        return min.get();
+    }
+
+    private StringBuilder getMin2(Collection<StringBuilder> col, Comparator<StringBuilder> c) {
+        assert (!col.isEmpty());
+        StringBuilder any = col.iterator().next();
+        StringBuilder min = col.stream().reduce(any, LambdaUtilities.minStringBuilderFunction(c),
+                LambdaUtilities.minSBBinaryOperator(c));
+        return min;
+    }
+
+    private void verifySlice(Iterator<StringBuilder> itOrg, Iterator<StringBuilder> itSliced,
+            int skip, int limit) {
+        int pos = 0;
+        while(itOrg.hasNext() && pos++ < skip)
+            itOrg.next();
+
+        while(itOrg.hasNext() && pos++ < limit)
+            assertEquals(itOrg.next(), itSliced.next());
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/stream/Streams/BasicTest.java	Sun Jan 27 12:55:52 2013 -0800
@@ -0,0 +1,149 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @summary Basic test for Streams's API
+ * @library ../..
+ * @(#) BasicTest.java
+ * @author Tristan Yan
+ * @run testng BasicTest
+ */
+
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.PrimitiveIterator;
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.IntConsumer;
+import java.util.function.IntUnaryOperator;
+import java.util.stream.IntStream;
+import java.util.stream.Stream;
+import java.util.stream.Streams;
+import static org.testng.Assert.*;
+import org.testng.annotations.Test;
+
+public class BasicTest {
+    private final static int ARRAY_SIZE = 1 << 12;
+
+    private final static Random rand = new Random(System.currentTimeMillis());
+
+    private final static String HELLO_WORLD = "Hello world";
+
+    @Test
+    public void testEmpty() {
+        final AtomicInteger accumulator = new AtomicInteger(0);
+        IntConsumer ic = i -> {
+            accumulator.getAndIncrement();
+        };
+        Streams.emptyPrimitiveSpliterator().forEach(ic);
+        assertEquals(accumulator.get(), 0);
+
+        assertEquals(Streams.emptyIntStream().toArray().length, 0);
+
+        assertEquals(Streams.emptyStream().toArray().length, 0);
+
+        assertFalse(Streams.emptyPrimitiveIterator().hasNext());
+
+        assertEquals(Streams.emptyPrimitiveSpliterator().estimateSize(), 0);
+
+        assertEquals(Streams.<String>emptySpliterator().estimateSize(), 0);
+    }
+
+    @Test
+    public void testGenerate() {
+        final int randomValue = rand.nextInt();
+        final int randomSize= rand.nextInt(Integer.MAX_VALUE);
+        IntStream is = Streams.generateInt(() -> randomValue);
+        assertEquals(is.spliterator().exactSizeIfKnown(), -1);
+
+        IntStream is1 = Streams.generateInt(() -> randomValue);
+        IntStream is2 = Streams.generateInt(() -> randomValue);
+        assertEquals(is1.limit(randomSize).max(), is2.limit(randomSize).min());
+
+        Stream<String> ss = Streams.generate(() -> HELLO_WORLD);
+        assertEquals(ss.spliterator().exactSizeIfKnown(), -1);
+        Stream<String> ss1 = Streams.generate(() -> HELLO_WORLD);
+        Stream<String> ss2 = Streams.generate(() -> HELLO_WORLD);
+        assertEquals(ss1.limit(randomSize).findAny(), ss2.limit(randomSize).findAny());
+
+        LambdaUtilities.IntOp op = LambdaUtilities.IntOp.values()[rand.nextInt(LambdaUtilities.IntOp.values().length)];
+        final int randomInit = rand.nextInt();
+        final int randomOpnd = rand.nextInt();
+        IntUnaryOperator iuo = LambdaUtilities.opIntUnaryOperator(op, randomOpnd);
+        IntStream isi = Streams.iterateInt(randomInit, iuo);
+        int limitation = rand.nextInt( 1 << 10 );
+        PrimitiveIterator<Integer> pi = isi.limit(limitation).iterator();
+
+        int next = randomInit;
+
+        while(pi.hasNext()) {
+            assertEquals(pi.nextInt(), next);
+            next = iuo.applyAsInt(next);
+        }
+
+        //below is time-consuming, need watch out if it's gonna affect our test
+        int start = rand.nextInt();
+        int end = rand.nextInt();
+
+        if(start > end) {
+            start = start ^ end;
+            end = end ^ start;
+            start = end ^ start;
+        }
+        PrimitiveIterator<Integer> it1 = Streams.intRange(start, end).iterator();
+        while(it1.hasNext())
+            assertEquals(it1.nextInt(), start++);
+        assertEquals(start, end);
+
+        int step = 2 << (rand.nextInt(31));
+        PrimitiveIterator<Integer> it2 = Streams.intRange(start, end, step).iterator();
+        while(it2.hasNext())
+            assertEquals(it2.nextInt(), start += step);
+        assertTrue(start + step > end);
+
+    }
+
+    @Test
+    public void testIterator() {
+        int seed = rand.nextInt();
+        int opRnd = rand.nextInt();
+        int selected = rand.nextInt(LambdaUtilities.IntOp.values().length);
+        LambdaUtilities.IntOp op = LambdaUtilities.IntOp.values()[selected];
+        int limitRnd = rand.nextInt(1 << 20);
+        IntUnaryOperator iuo = LambdaUtilities.opIntUnaryOperator(op, opRnd);
+        int[] arr = Streams.iterateInt(seed, iuo).limit(limitRnd).toArray();
+        assertEquals(arr.length, limitRnd);
+    }
+
+    @Test
+    public void testZip() {
+        int[] array1 = rand.ints().limit(ARRAY_SIZE).toArray();
+        int[] array2 = rand.ints().limit(ARRAY_SIZE).toArray();
+        Iterator<Integer> it = Streams.zip(Arrays.stream(array1).boxed(), Arrays.stream(array2).boxed(),
+                (i1, i2) -> i1 + i2).iterator();
+        for(int index = 0 ; index < ARRAY_SIZE; index++) {
+            assertEquals(it.next().intValue(), array1[index] + array2[index]);
+        }
+    }
+}