changeset 5318:8bc5bf9b4e05

Partial renaming of BiStream -> MapStream and associated necessary fixups.
author mduigou
date Fri, 27 Apr 2012 17:10:53 -0700
parents ca24bdbcbc97
children 6d2ad6682d99
files make/java/java/FILES_java.gmk src/share/classes/java/lang/BiStream.java src/share/classes/java/lang/BiVal.java src/share/classes/java/lang/BiValue.java src/share/classes/java/lang/Iterable.java src/share/classes/java/lang/MapStream.java src/share/classes/java/util/Enumeration.java src/share/classes/java/util/Map.java test-ng/tests/org/openjdk/tests/java/util/BiStreamTest.java test-ng/tests/org/openjdk/tests/java/util/MapStreamTest.java
diffstat 10 files changed, 785 insertions(+), 779 deletions(-) [+]
line wrap: on
line diff
--- a/make/java/java/FILES_java.gmk	Wed Apr 25 19:53:34 2012 -0700
+++ b/make/java/java/FILES_java.gmk	Fri Apr 27 17:10:53 2012 -0700
@@ -55,7 +55,7 @@
     java/lang/AssertionStatusDirectives.java \
     java/lang/Enum.java \
     java/lang/Iterable.java \
-    java/lang/BiStream.java \
+    java/lang/MapStream.java \
     java/lang/BiValue.java \
     java/lang/StrictMath.java \
     java/lang/Math.java \
--- a/src/share/classes/java/lang/BiStream.java	Wed Apr 25 19:53:34 2012 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,518 +0,0 @@
-/*
- * Copyright (c) 2003, 2010, 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-package java.lang;
-
-import java.util.*;
-import java.util.functions.*;
-
-/**
- * A stream of two element tuples. Depending on the source either of the tuple
- * elements may be unique.
- *
- * @since 1.8
- */
-public interface BiStream<T, U> /* extends Iterable<BiValue<T,U>> */ {
-
-    boolean isEmpty();
-
-    Iterable<T> lefts();
-
-    Iterable<U> rights();
-
-    /**
-     * Returns the first element from this Iterable. Depending on the source
-     * type of this Iterable repeated calls may-or-may-not return the same
-     * element.
-     *
-     * @return an element of the collection
-     * @throws NoSuchElementException if this Iterable contains no elements.
-     */
-    BiValue<T,U> getFirst() default {
-        Iterator<? extends BiValue<T,U>> iterator;
-
-        iterator = asIterable().iterator();
-
-        return iterator.hasNext() ? iterator.next() : null;
-    }
-
-    /**
-     * Returns the first item from this Iterable and require that there be no
-     * other elements in this Iterable.
-     *
-     * @return the element of the collection
-     * @throws NoSuchElementException if this Iterable contains no elements.
-     * @throws IllegalStateException if this Iterable contains more than one
-     * element.
-     */
-    BiValue<T,U> getOnly() default {
-        return Iterables.getOnly(asIterable());
-    }
-
-    /**
-     * Returns an element from this Iterable. Depending on the source type of
-     * this Iterable repeated calls may-or-may-not return the same element. If
-     * order is not important this method may be more efficient than
-     * {@link #getFirst() getfirst}.
-     *
-     * @return an element of the collection
-     * @throws NoSuchElementException if this Iterable contains no elements.
-     * element.
-     */
-    BiValue<T,U> getAny() default {
-        return getFirst();
-    }
-
-    Iterable<? extends BiValue<T, U>> asIterable();
-
-    BiStream<T, Iterable<U>> asMultiStream()  default {
-        return new BiStream<T, Iterable<U>>() {
-
-            @Override
-            public boolean isEmpty() {
-                return BiStream.this.isEmpty();
-            }
-
-            @Override
-            public Iterable<BiValue<T, Iterable<U>>> asIterable() {
-                return new Iterable<BiValue<T, Iterable<U>>>() {
-
-                    @Override
-                    public boolean isEmpty() {
-                        return BiStream.this.isEmpty();
-                    }
-
-                    @Override
-                    public Iterator<BiValue<T, Iterable<U>>> iterator() {
-                        return new Iterator<BiValue<T, Iterable<U>>>() {
-
-                            final Iterator<? extends BiValue<T, U>> source = BiStream.this.asIterable().iterator();
-
-                            @Override
-                            public boolean hasNext() {
-                                return source.hasNext();
-                            }
-
-                            @Override
-                            public BiValue<T, Iterable<U>> next() {
-                                BiValue<T, U> next = source.next();
-                                return new BiVal<T, Iterable<U>>(next.left(),
-                                        Collections.singletonList(next.right()));
-                            }
-                        };
-                    }
-                };
-            }
-
-            @Override
-            public Iterable<T> lefts() {
-                return BiStream.this.lefts();
-            }
-
-            @Override
-            public Iterable<Iterable<U>> rights() {
-                return new Iterable<Iterable<U>>() {
-
-                    @Override
-                    public boolean isEmpty() {
-                        return BiStream.this.isEmpty();
-                    }
-
-                    @Override
-                    public Iterator<Iterable<U>> iterator() {
-                        return new Iterator<Iterable<U>>() {
-
-                            final Iterator<U> source = BiStream.this.rights().iterator();
-
-                            @Override
-                            public boolean hasNext() {
-                                return source.hasNext();
-                            }
-
-                            @Override
-                            public Iterable<U> next() {
-                                return Collections.singletonList(source.next());
-                            }
-                        };
-                    }
-                };
-            }
-        };
-    }
-
-    void forEach(BiBlock<? super T, ? super U> block) default {
-        for(BiValue<T,U> each : asIterable()) {
-            block.apply(each.left(), each.right());
-        }
-    }
-
-    BiStream<T, U> filter(final BiPredicate<? super T, ? super U> predicate) default {
-        return new BiStream<T, U>() {
-
-            @Override
-            public boolean isEmpty() {
-                // XXX we need to decide if isEmpty() false can be a "lie".
-
-                return BiStream.this.isEmpty();
-            }
-
-            @Override
-            public Iterable<BiValue<T, U>> asIterable() {
-                return new Iterable<BiValue<T, U>>() {
-
-                    @Override
-                    public boolean isEmpty() {
-                        return BiStream.this.isEmpty();
-                    }
-
-                    @Override
-                    public Iterator<BiValue<T, U>> iterator() {
-                        return new Iterator<BiValue<T, U>>() {
-
-                            final Iterator<? extends BiValue<T, U>> source = BiStream.this.asIterable().iterator();
-
-                            BiValue<T,U> next;
-
-                            BiValue<T,U> getNext() {
-                                while(null == next) {
-                                    if(!source.hasNext()) {
-                                        break;
-                                    }
-
-                                   BiValue<T,U> unfiltered = source.next();
-
-                                   if(predicate.eval(unfiltered.left(), unfiltered.right())) {
-                                       next = unfiltered;
-                                       break;
-                                   }
-                                }
-
-                                return next;
-                            }
-
-                            @Override
-                            public boolean hasNext() {
-                                return null != getNext();
-                            }
-
-                            @Override
-                            public BiValue<T, U> next() {
-                                BiValue<T,U> result = getNext();
-                                if(null == result) {
-                                    throw new NoSuchElementException("no element");
-                                }
-
-                                next = null;
-
-                                return result;
-                            }
-                        };
-                    }
-                };
-            }
-
-            @Override
-            public Iterable<T> lefts() {
-                final Iterable<BiValue<T,U>> filteredElements = asIterable();
-
-                return new Iterable<T>() {
-
-                    @Override
-                    public boolean isEmpty() {
-                        return BiStream.this.isEmpty();
-                    }
-
-                    @Override
-                    public Iterator<T> iterator() {
-
-                        return new Iterator<T>() {
-
-                            final Iterator<? extends BiValue<T, U>> source = filteredElements.iterator();
-
-
-                            @Override
-                            public boolean hasNext() {
-                                return source.hasNext();
-                            }
-
-                            @Override
-                            public T next() {
-                                return source.next().left();
-                            }
-                        };
-                    }
-                };
-            }
-
-            @Override
-            public Iterable<U> rights() {
-                final Iterable<BiValue<T,U>> filteredElements = asIterable();
-
-                return new Iterable<U>() {
-
-                    @Override
-                    public boolean isEmpty() {
-                        return BiStream.this.isEmpty();
-                    }
-
-                    @Override
-                    public Iterator<U> iterator() {
-
-                        return new Iterator<U>() {
-
-                            final Iterator<? extends BiValue<T, U>> source = filteredElements.iterator();
-
-
-                            @Override
-                            public boolean hasNext() {
-                                return source.hasNext();
-                            }
-
-                            @Override
-                            public U next() {
-                                return source.next().right();
-                            }
-                        };
-                    }
-                };
-            }
-        };
-    }
-
-    BiStream<T, U> filterLefts(final Predicate<T> filter) default {
-        return filter( (l, r) -> filter.test(l));
-    }
-
-    BiStream<T, U> filterRights(final Predicate<U> filter) default {
-        return filter( (l, r) -> filter.test(r));
-    }
-
-    <V> BiStream<T, V> map(final BiMapper<T, U, V> mapper) default {
-        return new BiStream<T, V>() {
-
-            @Override
-            public boolean isEmpty() {
-                return BiStream.this.isEmpty();
-            }
-
-            @Override
-            public Iterable<T> lefts() {
-                return BiStream.this.lefts();
-            }
-
-            @Override
-            public Iterable<V> rights() {
-                return new Iterable<V>() {
-
-                    @Override
-                    public boolean isEmpty() {
-                        return BiStream.this.isEmpty();
-                    }
-
-                    @Override
-                    public Iterator<V> iterator() {
-                        return new Iterator<V>() {
-
-                            final Iterator<? extends BiValue<T, U>> source = BiStream.this.asIterable().iterator();
-
-                            @Override
-                            public boolean hasNext() {
-                                return source.hasNext();
-                            }
-
-                            @Override
-                            public V next() {
-                                BiValue<T,U> unmapped = source.next();
-
-                                return mapper.map(unmapped.left(), unmapped.right());
-                            }
-                        };
-                    }
-                };
-            }
-
-            @Override
-            public Iterable<BiValue<T, V>> asIterable() {
-                return new Iterable<BiValue<T, V>>() {
-
-                    @Override
-                    public boolean isEmpty() {
-                        return BiStream.this.isEmpty();
-                    }
-
-                    @Override
-                    public Iterator<BiValue<T, V>> iterator() {
-                        return new Iterator<BiValue<T, V>>() {
-
-                            final Iterator<? extends BiValue<T, U>> source = BiStream.this.asIterable().iterator();
-
-                            @Override
-                            public boolean hasNext() {
-                                return source.hasNext();
-                            }
-
-                            @Override
-                            public BiValue<T, V> next() {
-                                BiValue<T,U> unmapped = source.next();
-
-                                return new BiVal<>(unmapped.left(), mapper.map(unmapped.left(), unmapped.right()));
-                            }
-                        };
-                    }
-                };
-            }
-        };
-    }
-
-    <V> BiStream<T, V> mapValues(final Mapper<U, V> mapper) default {
-        return map( (l,r ) -> mapper.map(r));
-    }
-
-    <V> BiStream<T, Iterable<V>> mapValuesMulti(final BiMapper<? super T, ? super U, Iterable<V>> mapper) default {
-        return new BiStream<T, Iterable<V>>() {
-
-            @Override
-            public boolean isEmpty() {
-                return BiStream.this.isEmpty();
-            }
-
-            @Override
-            public Iterable<T> lefts() {
-                return BiStream.this.lefts();
-            }
-
-            @Override
-            public Iterable<Iterable<V>> rights() {
-                return new Iterable<Iterable<V>>() {
-
-                    @Override
-                    public boolean isEmpty() {
-                        return BiStream.this.isEmpty();
-                    }
-
-                    @Override
-                    public Iterator<Iterable<V>> iterator() {
-                        return new Iterator<Iterable<V>>() {
-
-                            final Iterator<? extends BiValue<T, U>> source = BiStream.this.asIterable().iterator();
-
-                            @Override
-                            public boolean hasNext() {
-                                return source.hasNext();
-                            }
-
-                            @Override
-                            public Iterable<V> next() {
-                                BiValue<T,U> unmapped = source.next();
-
-                                return mapper.map(unmapped.left(), unmapped.right());
-                            }
-                        };
-                    }
-                };
-            }
-
-            @Override
-            public Iterable<BiValue<T, Iterable<V>>> asIterable() {
-                return new Iterable<BiValue<T, Iterable<V>>>() {
-
-                    @Override
-                    public boolean isEmpty() {
-                        return BiStream.this.isEmpty();
-                    }
-
-                    @Override
-                    public Iterator<BiValue<T, Iterable<V>>> iterator() {
-                        return new Iterator<BiValue<T, Iterable<V>>>() {
-
-                            final Iterator<? extends BiValue<T, U>> source = BiStream.this.asIterable().iterator();
-
-                            @Override
-                            public boolean hasNext() {
-                                return source.hasNext();
-                            }
-
-                            @Override
-                            public BiValue<T, Iterable<V>> next() {
-                                BiValue<T,U> unmapped = source.next();
-
-                                return new BiVal<>(unmapped.left(), mapper.map(unmapped.left(), unmapped.right()));
-                            }
-                        };
-                    }
-                };
-            }
-        };
-    }
-
-    <A extends Map<? super T, ? super U>> A into(A destination) default {
-        forEach( (l, r) -> { destination.put(l, r); });
-        return destination;
-    }
-
-    boolean anyMatch(BiPredicate<? super T, ? super U> predicate)
-        default {
-        for (BiValue<T, U> each : asIterable()) {
-            if (predicate.eval(each.left(), each.right())) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    boolean allMatch(BiPredicate<? super T, ? super U> predicate)
-        default {
-        for (BiValue<T, U> each : asIterable()) {
-            if (!predicate.eval(each.left(), each.right())) {
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    boolean noneMatch(BiPredicate<? super T, ? super U> predicate) default {
-        return !anyMatch(predicate);
-    }
-
-    BiStream<T, U> sorted(Comparator<? super T> comparator) default {
-        TreeMap<T,U> result = new TreeMap<>(comparator);
-        forEach( (l, r) -> { result.put(l, r); } );
-
-        return result;
-    }
-
-    BiStream<T, U> merge(BiStream<T, U> other) default {
-        Map<T, U> union = new HashMap<>();
-        into(union);
-        return other.into(union);
-    }
-//
-//    BiStream<T, Iterable<U>> merge(BiStream<T, Iterable<U>> other) default {
-//            Map<T, Iterable<U>> union = new HashMap<>();
-//        asMultiStream().into(union);
-//        return other.into(union);
-//    }
-}
--- a/src/share/classes/java/lang/BiVal.java	Wed Apr 25 19:53:34 2012 -0700
+++ b/src/share/classes/java/lang/BiVal.java	Fri Apr 27 17:10:53 2012 -0700
@@ -24,23 +24,23 @@
  */
 package java.lang;
 
-class BiVal<T, U> implements BiValue<T, U> {
+class BiVal<K, V> implements BiValue<K, V> {
 
-    public final T left;
-    public final U right;
+    public final K key;
+    public final V value;
 
-    public BiVal(T left, U right) {
-        this.left = left;
-        this.right = right;
+    public BiVal(K left, V right) {
+        this.key = left;
+        this.value = right;
     }
 
     @Override
-    public T left() {
-        return left;
+    public K getKey() {
+        return key;
     }
 
     @Override
-    public U right() {
-        return right;
+    public V getValue() {
+        return value;
     }
 }
--- a/src/share/classes/java/lang/BiValue.java	Wed Apr 25 19:53:34 2012 -0700
+++ b/src/share/classes/java/lang/BiValue.java	Fri Apr 27 17:10:53 2012 -0700
@@ -31,14 +31,14 @@
  */
 public interface BiValue<T, U> {
 
-    T left();
+    T getKey();
 
-    U right();
+    U getValue();
 
     /**
      * Compares the specified object with this entry for equality. Returns
-     * {@code true} if the given object is also a map entry and the two entries 
-     * represent the same mapping. More formally, two entries {@code e1} and 
+     * {@code true} if the given object is also a map entry and the two entries
+     * represent the same mapping. More formally, two entries {@code e1} and
      * {@code e2} represent the same mapping if<pre>
      *     Objects.equals(e1.left(), e2.left()) &amp; &amp;
      * Objects.equals(e1.right(), e2.right())
@@ -53,8 +53,8 @@
         if (other instanceof BiValue) {
             @SuppressWarnings("raw")
             BiValue likeMe = (BiValue) other;
-            return Objects.equals(left(), likeMe.left())
-                    && Objects.equals(right(), likeMe.right());
+            return Objects.equals(getKey(), likeMe.getKey())
+                    && Objects.equals(getValue(), likeMe.getValue());
         }
 
         return false;
@@ -76,6 +76,6 @@
      */
     @Override
     int hashCode() default {
-        return Objects.hashCode(left()) ^ Objects.hashCode(right());
+        return Objects.hashCode(getKey()) ^ Objects.hashCode(getValue());
     }
 }
--- a/src/share/classes/java/lang/Iterable.java	Wed Apr 25 19:53:34 2012 -0700
+++ b/src/share/classes/java/lang/Iterable.java	Fri Apr 27 17:10:53 2012 -0700
@@ -296,8 +296,8 @@
         return Iterables.uniqueElements(this);
     }
 
-    <U> BiStream<T,U> mapped(final Mapper<? super T, ? extends U> mapper) default {
-        return new BiStream<T, U>() {
+    <U> MapStream<T,U> mapped(final Mapper<? super T, ? extends U> mapper) default {
+        return new MapStream<T, U>() {
 
             @Override
             public boolean isEmpty() {
@@ -305,12 +305,12 @@
             }
 
             @Override
-            public Iterable<T> lefts() {
+            public Iterable<T> inputs() {
                 return Iterable.this; // duh!
             }
 
             @Override
-            public Iterable<U> rights() {
+            public Iterable<U> values() {
                 return Iterable.this.map(mapper);
             }
 
@@ -347,11 +347,11 @@
         };
     }
 
-    <U> BiStream<T, Iterable<U>> groupBy(Mapper<? super T, ? extends U> mapper)default {
+    <U> MapStream<T, Iterable<U>> groupBy(Mapper<? super T, ? extends U> mapper)default {
         throw new UnsupportedOperationException("Not implemented");
     }
 
-    <U> BiStream<T, Iterable<U>> groupByMulti(Mapper<? super T, ? extends Iterable<? extends U>> mapper)default {
+    <U> MapStream<T, Iterable<U>> groupByMulti(Mapper<? super T, ? extends Iterable<? extends U>> mapper)default {
         throw new UnsupportedOperationException("Not implemented");
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/classes/java/lang/MapStream.java	Fri Apr 27 17:10:53 2012 -0700
@@ -0,0 +1,522 @@
+/*
+ * Copyright (c) 2003, 2010, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package java.lang;
+
+import java.util.*;
+import java.util.functions.*;
+
+/**
+ * A stream of two element tuples. Depending on the source either of the tuple
+ * elements may be unique.
+ *
+ * @since 1.8
+ */
+public interface MapStream<K, V> /* extends Iterable<BiValue<T,U>> */ {
+
+    boolean isEmpty();
+
+    /**
+     *
+     * XXX this name is temporary
+     */
+    Iterable<K> inputs();
+
+    Iterable<V> values();
+
+    Iterable<? extends BiValue<K, V>> asIterable();
+
+    /**
+     * Returns the first element from this Iterable. Depending on the source
+     * type of this Iterable repeated calls may-or-may-not return the same
+     * element.
+     *
+     * @return an element of the collection
+     * @throws NoSuchElementException if this Iterable contains no elements.
+     */
+    BiValue<K,V> getFirst() default {
+        Iterator<? extends BiValue<K,V>> iterator;
+
+        iterator = asIterable().iterator();
+
+        return iterator.hasNext() ? iterator.next() : null;
+    }
+
+    /**
+     * Returns the first item from this Iterable and require that there be no
+     * other elements in this Iterable.
+     *
+     * @return the element of the collection
+     * @throws NoSuchElementException if this Iterable contains no elements.
+     * @throws IllegalStateException if this Iterable contains more than one
+     * element.
+     */
+    BiValue<K,V> getOnly() default {
+        return Iterables.getOnly(asIterable());
+    }
+
+    /**
+     * Returns an element from this Iterable. Depending on the source type of
+     * this Iterable repeated calls may-or-may-not return the same element. If
+     * order is not important this method may be more efficient than
+     * {@link #getFirst() getfirst}.
+     *
+     * @return an element of the collection
+     * @throws NoSuchElementException if this Iterable contains no elements.
+     * element.
+     */
+    BiValue<K,V> getAny() default {
+        return getFirst();
+    }
+
+    MapStream<K, Iterable<V>> asMultiStream() default {
+        return new MapStream<K, Iterable<V>>() {
+
+            @Override
+            public boolean isEmpty() {
+                return MapStream.this.isEmpty();
+            }
+
+            @Override
+            public Iterable<BiValue<K, Iterable<V>>> asIterable() {
+                return new Iterable<BiValue<K, Iterable<V>>>() {
+
+                    @Override
+                    public boolean isEmpty() {
+                        return MapStream.this.isEmpty();
+                    }
+
+                    @Override
+                    public Iterator<BiValue<K, Iterable<V>>> iterator() {
+                        return new Iterator<BiValue<K, Iterable<V>>>() {
+
+                            final Iterator<? extends BiValue<K, V>> source = MapStream.this.asIterable().iterator();
+
+                            @Override
+                            public boolean hasNext() {
+                                return source.hasNext();
+                            }
+
+                            @Override
+                            public BiValue<K, Iterable<V>> next() {
+                                BiValue<K, V> next = source.next();
+                                return new BiVal<K, Iterable<V>>(next.getKey(),
+                                        Collections.singletonList(next.getValue()));
+                            }
+                        };
+                    }
+                };
+            }
+
+            @Override
+            public Iterable<K> inputs() {
+                return MapStream.this.inputs();
+            }
+
+            @Override
+            public Iterable<Iterable<V>> values() {
+                return new Iterable<Iterable<V>>() {
+
+                    @Override
+                    public boolean isEmpty() {
+                        return MapStream.this.isEmpty();
+                    }
+
+                    @Override
+                    public Iterator<Iterable<V>> iterator() {
+                        return new Iterator<Iterable<V>>() {
+
+                            final Iterator<V> source = MapStream.this.values().iterator();
+
+                            @Override
+                            public boolean hasNext() {
+                                return source.hasNext();
+                            }
+
+                            @Override
+                            public Iterable<V> next() {
+                                return Collections.singletonList(source.next());
+                            }
+                        };
+                    }
+                };
+            }
+        };
+    }
+
+    void forEach(BiBlock<? super K, ? super V> block) default {
+        for(BiValue<K,V> each : asIterable()) {
+            block.apply(each.getKey(), each.getValue());
+        }
+    }
+
+    MapStream<K, V> filter(final BiPredicate<? super K, ? super V> predicate) default {
+        return new MapStream<K, V>() {
+
+            @Override
+            public boolean isEmpty() {
+                // XXX we need to decide if isEmpty() false can be a "lie".
+
+                return MapStream.this.isEmpty();
+            }
+
+            @Override
+            public Iterable<BiValue<K, V>> asIterable() {
+                return new Iterable<BiValue<K, V>>() {
+
+                    @Override
+                    public boolean isEmpty() {
+                        return MapStream.this.isEmpty();
+                    }
+
+                    @Override
+                    public Iterator<BiValue<K, V>> iterator() {
+                        return new Iterator<BiValue<K, V>>() {
+
+                            final Iterator<? extends BiValue<K, V>> source = MapStream.this.asIterable().iterator();
+
+                            BiValue<K,V> next;
+
+                            BiValue<K,V> getNext() {
+                                while(null == next) {
+                                    if(!source.hasNext()) {
+                                        break;
+                                    }
+
+                                   BiValue<K,V> unfiltered = source.next();
+
+                                   if(predicate.eval(unfiltered.getKey(), unfiltered.getValue())) {
+                                       next = unfiltered;
+                                       break;
+                                   }
+                                }
+
+                                return next;
+                            }
+
+                            @Override
+                            public boolean hasNext() {
+                                return null != getNext();
+                            }
+
+                            @Override
+                            public BiValue<K, V> next() {
+                                BiValue<K,V> result = getNext();
+                                if(null == result) {
+                                    throw new NoSuchElementException("no element");
+                                }
+
+                                next = null;
+
+                                return result;
+                            }
+                        };
+                    }
+                };
+            }
+
+            @Override
+            public Iterable<K> inputs() {
+                final Iterable<BiValue<K,V>> filteredElements = asIterable();
+
+                return new Iterable<K>() {
+
+                    @Override
+                    public boolean isEmpty() {
+                        return MapStream.this.isEmpty();
+                    }
+
+                    @Override
+                    public Iterator<K> iterator() {
+
+                        return new Iterator<K>() {
+
+                            final Iterator<? extends BiValue<K, V>> source = filteredElements.iterator();
+
+
+                            @Override
+                            public boolean hasNext() {
+                                return source.hasNext();
+                            }
+
+                            @Override
+                            public K next() {
+                                return source.next().getKey();
+                            }
+                        };
+                    }
+                };
+            }
+
+            @Override
+            public Iterable<V> values() {
+                final Iterable<BiValue<K,V>> filteredElements = asIterable();
+
+                return new Iterable<V>() {
+
+                    @Override
+                    public boolean isEmpty() {
+                        return MapStream.this.isEmpty();
+                    }
+
+                    @Override
+                    public Iterator<V> iterator() {
+
+                        return new Iterator<V>() {
+
+                            final Iterator<? extends BiValue<K, V>> source = filteredElements.iterator();
+
+
+                            @Override
+                            public boolean hasNext() {
+                                return source.hasNext();
+                            }
+
+                            @Override
+                            public V next() {
+                                return source.next().getValue();
+                            }
+                        };
+                    }
+                };
+            }
+        };
+    }
+
+    MapStream<K, V> filterKeys(final Predicate<K> filter) default {
+        return filter( (k, v) -> filter.test(k));
+    }
+
+    MapStream<K, V> filterValues(final Predicate<V> filter) default {
+        return filter( (k, v) -> filter.test(v));
+    }
+
+    <W> MapStream<K, W> map(final BiMapper<K, V, W> mapper) default {
+        return new MapStream<K, W>() {
+
+            @Override
+            public boolean isEmpty() {
+                return MapStream.this.isEmpty();
+            }
+
+            @Override
+            public Iterable<K> inputs() {
+                return MapStream.this.inputs();
+            }
+
+            @Override
+            public Iterable<W> values() {
+                return new Iterable<W>() {
+
+                    @Override
+                    public boolean isEmpty() {
+                        return MapStream.this.isEmpty();
+                    }
+
+                    @Override
+                    public Iterator<W> iterator() {
+                        return new Iterator<W>() {
+
+                            final Iterator<? extends BiValue<K, V>> source = MapStream.this.asIterable().iterator();
+
+                            @Override
+                            public boolean hasNext() {
+                                return source.hasNext();
+                            }
+
+                            @Override
+                            public W next() {
+                                BiValue<K,V> unmapped = source.next();
+
+                                return mapper.map(unmapped.getKey(), unmapped.getValue());
+                            }
+                        };
+                    }
+                };
+            }
+
+            @Override
+            public Iterable<BiValue<K, W>> asIterable() {
+                return new Iterable<BiValue<K, W>>() {
+
+                    @Override
+                    public boolean isEmpty() {
+                        return MapStream.this.isEmpty();
+                    }
+
+                    @Override
+                    public Iterator<BiValue<K, W>> iterator() {
+                        return new Iterator<BiValue<K, W>>() {
+
+                            final Iterator<? extends BiValue<K, V>> source = MapStream.this.asIterable().iterator();
+
+                            @Override
+                            public boolean hasNext() {
+                                return source.hasNext();
+                            }
+
+                            @Override
+                            public BiValue<K, W> next() {
+                                BiValue<K,V> unmapped = source.next();
+
+                                return new BiVal<>(unmapped.getKey(), mapper.map(unmapped.getKey(), unmapped.getValue()));
+                            }
+                        };
+                    }
+                };
+            }
+        };
+    }
+
+    <W> MapStream<K, W> mapValues(final Mapper<V, W> mapper) default {
+        return map( (k, v) -> mapper.map(v));
+    }
+
+    <W> MapStream<K, Iterable<W>> mapValuesMulti(final BiMapper<? super K, ? super V, Iterable<W>> mapper) default {
+        return new MapStream<K, Iterable<W>>() {
+
+            @Override
+            public boolean isEmpty() {
+                return MapStream.this.isEmpty();
+            }
+
+            @Override
+            public Iterable<K> inputs() {
+                return MapStream.this.inputs();
+            }
+
+            @Override
+            public Iterable<Iterable<W>> values() {
+                return new Iterable<Iterable<W>>() {
+
+                    @Override
+                    public boolean isEmpty() {
+                        return MapStream.this.isEmpty();
+                    }
+
+                    @Override
+                    public Iterator<Iterable<W>> iterator() {
+                        return new Iterator<Iterable<W>>() {
+
+                            final Iterator<? extends BiValue<K, V>> source = MapStream.this.asIterable().iterator();
+
+                            @Override
+                            public boolean hasNext() {
+                                return source.hasNext();
+                            }
+
+                            @Override
+                            public Iterable<W> next() {
+                                BiValue<K,V> unmapped = source.next();
+
+                                return mapper.map(unmapped.getKey(), unmapped.getValue());
+                            }
+                        };
+                    }
+                };
+            }
+
+            @Override
+            public Iterable<BiValue<K, Iterable<W>>> asIterable() {
+                return new Iterable<BiValue<K, Iterable<W>>>() {
+
+                    @Override
+                    public boolean isEmpty() {
+                        return MapStream.this.isEmpty();
+                    }
+
+                    @Override
+                    public Iterator<BiValue<K, Iterable<W>>> iterator() {
+                        return new Iterator<BiValue<K, Iterable<W>>>() {
+
+                            final Iterator<? extends BiValue<K, V>> source = MapStream.this.asIterable().iterator();
+
+                            @Override
+                            public boolean hasNext() {
+                                return source.hasNext();
+                            }
+
+                            @Override
+                            public BiValue<K, Iterable<W>> next() {
+                                BiValue<K,V> unmapped = source.next();
+
+                                return new BiVal<>(unmapped.getKey(), mapper.map(unmapped.getKey(), unmapped.getValue()));
+                            }
+                        };
+                    }
+                };
+            }
+        };
+    }
+
+    <A extends Map<? super K, ? super V>> A into(A destination) default {
+        forEach( (l, r) -> { destination.put(l, r); });
+        return destination;
+    }
+
+    boolean anyMatch(BiPredicate<? super K, ? super V> predicate)
+        default {
+        for (BiValue<K, V> each : asIterable()) {
+            if (predicate.eval(each.getKey(), each.getValue())) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    boolean allMatch(BiPredicate<? super K, ? super V> predicate)
+        default {
+        for (BiValue<K, V> each : asIterable()) {
+            if (!predicate.eval(each.getKey(), each.getValue())) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    boolean noneMatch(BiPredicate<? super K, ? super V> predicate) default {
+        return !anyMatch(predicate);
+    }
+
+    MapStream<K, V> sorted(Comparator<? super K> comparator) default {
+        TreeMap<K,V> result = new TreeMap<>(comparator);
+        forEach( (k, v) -> { result.put(k, v); } );
+
+        return result;
+    }
+
+    MapStream<K, V> merge(MapStream<K, V> other)default {
+        Map<K, V> union = new HashMap<>();
+        into(union);
+        return other.into(union);
+    }
+//
+//    BiStream<T, Iterable<U>> merge(BiStream<T, Iterable<U>> other) default {
+//            Map<T, Iterable<U>> union = new HashMap<>();
+//        asMultiStream().into(union);
+//        return other.into(union);
+//    }
+}
--- a/src/share/classes/java/util/Enumeration.java	Wed Apr 25 19:53:34 2012 -0700
+++ b/src/share/classes/java/util/Enumeration.java	Fri Apr 27 17:10:53 2012 -0700
@@ -43,7 +43,7 @@
  * <p>
  * NOTE: The functionality of this interface is duplicated by the Iterator
  * interface.  In addition, Iterator adds an optional remove operation, and
- * has shorter method names.  New implementations should consider using
+ * has shorter method names.  New implementations should strongly consider using
  * Iterator in preference to Enumeration.
  *
  * @see     java.util.Iterator
@@ -76,4 +76,18 @@
      * @exception  NoSuchElementException  if no more elements exist.
      */
     E nextElement();
+//
+//    /**
+//     * {@inheritDoc}
+//     */
+//    E next() default {
+//        return nextElement();
+//    }
+//
+//    /**
+//     * {@inheritDoc}
+//     */
+//    boolean hasNext() default {
+//        return hasMoreElements();
+//    }
 }
--- a/src/share/classes/java/util/Map.java	Wed Apr 25 19:53:34 2012 -0700
+++ b/src/share/classes/java/util/Map.java	Fri Apr 27 17:10:53 2012 -0700
@@ -116,23 +116,18 @@
  * @see Set
  * @since 1.2
  */
-public interface Map<K,V> extends BiStream<K, V>  {
-    
+public interface Map<K,V> extends MapStream<K, V>  {
+
     @Override
-    Iterable<K> lefts() default {
+    Iterable<K> inputs() default {
         return keySet();
     }
-    
-    @Override
-    Iterable<V> rights() default {
-        return values();
-    }
-    
+
     @Override
     Iterable<? extends BiValue<K,V>> asIterable() default {
         return entrySet();
     }
-    
+
     // Query Operations
 
     /**
@@ -379,15 +374,6 @@
      * @since 1.2
      */
     interface Entry<K,V> extends BiValue<K,V> {
-        K left() default {
-            return getKey();
-        }
-        
-        V right() default {
-            return getValue();
-        }
-       
-        
         /**
          * Returns the key corresponding to this entry.
          *
@@ -396,6 +382,7 @@
          *         required to, throw this exception if the entry has been
          *         removed from the backing map.
          */
+        @Override
         K getKey();
 
         /**
@@ -408,6 +395,7 @@
          *         required to, throw this exception if the entry has been
          *         removed from the backing map.
          */
+        @Override
         V getValue();
 
         /**
--- a/test-ng/tests/org/openjdk/tests/java/util/BiStreamTest.java	Wed Apr 25 19:53:34 2012 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,217 +0,0 @@
-/*
- * 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * 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.
- */
-
-package org.openjdk.tests.java.util;
-
-import java.util.*;
-
-import org.testng.annotations.Test;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-import static org.openjdk.tests.java.util.LambdaTestHelpers.*;
-
-/**
- *
- * @author mike
- */
-@Test(groups = { "unit", "lambda" })
-public class BiStreamTest {
-    static final Integer[] KEYS = {0,1,2,3};
-    static final String[] VALUES = {"zero", "one", "two", "three"};
-    
-    final Map<Integer, String> map = new HashMap<>();
-    final BiStream<Integer, String> test = Collections.unmodifiableMap(map);
-    
-    BiStreamTest () {
-    Iterator<String> values = Arrays.asList(VALUES).iterator();
-        for(Integer key : KEYS) {
-            map.put(key, values.next());
-        }
-        
-        BiValue<Integer,String> found = null;
-        for(BiValue<Integer,String> each : test.asIterable()) {
-            if(0 == each.left()) {
-                found = each;
-                break;
-            }
-        }
-    }
-    
-    
-    public void testIsEmpty() {
-        assertFalse(test.isEmpty());
-        assertTrue(((BiStream<?,?>) Collections.emptyMap()).isEmpty());        
-    }
-    
-    public void testGetFirst() {
-        assertNotEquals(null, test.getFirst());
-        assertEquals(null, ((BiStream<?,?>) Collections.emptyMap()).getFirst());        
-    }
-        
-    public void testGetAny() {
-        assertNotEquals(null, test.getAny());
-        assertEquals(null, ((BiStream<?,?>) Collections.emptyMap()).getAny());        
-    }
-        
-    public void testGetOnlyGood() {
-        assertNotEquals(null, ((BiStream<String,String>) Collections.singletonMap("foo","bar")).getOnly());        
-    }
-    
-    @Test(expectedExceptions=IllegalStateException.class)
-    public void testGetOnlyBad() {
-        BiValue<Integer,String> notOnly = test.getOnly();
-    }
-
-    public void testLefts() {               
-        Iterable<Integer> lefts = test.lefts();
-        Collection<Integer> leftInto = new ArrayList<>();
-        lefts.into(leftInto);
-        
-        assertTrue(Arrays.asList(KEYS).containsAll(leftInto) &&
-                leftInto.containsAll(Arrays.asList(KEYS)));
-    }
-    
-    public void testRights() {     
-        Iterable<String> rights = test.rights();
-        
-        Collection<String> rightsInto = new ArrayList<>();
-        rights.into(rightsInto);
-        
-        assertTrue(Arrays.asList(VALUES).containsAll(rightsInto) &&
-                rightsInto.containsAll(Arrays.asList(VALUES)));
-    }
-    
-    public void testAsIterable() {
-        Iterable<? extends BiValue<Integer,String>> iterable = test.asIterable();
-        
-        Set<BiValue<Integer,String>> into = new HashSet<>();
-        for(BiValue<Integer,String> element : iterable) {
-            into.add(element);
-        }
-        
-        assertEquals(into, map.entrySet());
-    }
-    
-    public void testAsMultiStream() {
-        BiStream<Integer, Iterable<String>> multi = test.asMultiStream();
-        
-        List<BiValue<Integer, Iterable<String>>> into = new ArrayList<>();
-        for(BiValue<Integer,Iterable<String>> element : multi.asIterable()) {
-            into.add(element);
-        }
-        
-        for(BiValue<Integer,Iterable<String>> pair : into) {
-            Integer key = pair.left();
-            Iterable<String> value = pair.right();
-            
-            assertTrue(Arrays.asList(KEYS).contains(key));
-            
-            List<String> forKey = new ArrayList<>();
-            value.into(forKey);
-            
-            assertTrue(1 == forKey.size());
-            assertTrue(Arrays.asList(VALUES).contains(forKey.getFirst()));
-        }
-    }
-    
-    public void testAllMatch() {
-        assertTrue(test.allMatch( (l,r) -> l >= 0), "should all be positive");
-        assertTrue(test.allMatch( (l,r) -> r.length() > 0), "should all be non-empty");
-    };
-    
-    public void testNoneMatch() {
-        assertTrue(test.noneMatch( (l,r) -> l < 0), "should be no negatives");
-        assertTrue(test.noneMatch( (l,r) -> r.length() == 0), "should be no empty strings");
-    };
-    
-    public void testAnyMatch() {
-        assertTrue(test.anyMatch( (l,r) -> l == 2), "there should be a '2'");
-        assertTrue(test.anyMatch( (l,r) -> "two".equals(r)),"there should be a 'two'");
-    };
-    
-    public void testForEach() {
-        int heinous[] = new int[1];
-        
-        test.forEach((l,r) -> {heinous[0]++;});
-        assertEquals(map.size(), heinous[0], "element count does not equal source size");
-    }
-    
-    public void testFilter() {
-        Map<Integer, String> into = new HashMap<>();
-        
-        test.filter((l,r) -> (l % 2) == 0).into(into);
-        assertTrue(into.size() == 2);
-        into.clear();
-        test.filter((l,r) -> "two".equals(r)).into(into);
-        assertTrue(into.size() == 1);
-    }
-    
-    public void testFilterLeft() {
-        Map<Integer, String> into = new HashMap<>();
-        
-        test.filterLefts(l -> l % 2 == 0).into(into);
-        assertTrue(into.size() == 2);       
-    }
-    
-    public void testFilterRight() {
-        Map<Integer, String> into = new HashMap<>();
-        
-        test.filterRights(r -> "two".equals(r)).into(into);   
-        assertTrue(into.size() == 1);
-    }
-    
-    public void testMap() {
-        for(BiValue<Integer,String> each : test.map((l,r) -> l.toString()).asIterable()) {
-            assertEquals((int) each.left(), Integer.parseInt(each.right()), "values not equal");
-        }
-    }
-    
-    public void testMapValues() {
-        
-    }
-    
-    public void testMapValuesMulti() {
-        
-    }
-    
-    public void testSorted() {
-        // standard order
-        int min = Integer.MIN_VALUE;
-        for(Integer each : test.sorted((one, two) -> one - two).lefts()) {
-            assertTrue(min <= each, "Not in ascending order");
-            min = each;
-        }
-
-        // reverse order
-        int max = Integer.MAX_VALUE;
-        for(Integer each : test.sorted((one, two) -> two - one).lefts()) {
-            assertTrue(max >= each, "Not in descending order");
-            max = each;
-        }        
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test-ng/tests/org/openjdk/tests/java/util/MapStreamTest.java	Fri Apr 27 17:10:53 2012 -0700
@@ -0,0 +1,217 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package org.openjdk.tests.java.util;
+
+import java.util.*;
+
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.openjdk.tests.java.util.LambdaTestHelpers.*;
+
+/**
+ *
+ * @author mike
+ */
+@Test(groups = { "unit", "lambda" })
+public class MapStreamTest {
+    static final Integer[] KEYS = {0,1,2,3};
+    static final String[] VALUES = {"zero", "one", "two", "three"};
+
+    final Map<Integer, String> map = new HashMap<>();
+    final MapStream<Integer, String> test = Collections.unmodifiableMap(map);
+
+    MapStreamTest () {
+    Iterator<String> values = Arrays.asList(VALUES).iterator();
+        for(Integer key : KEYS) {
+            map.put(key, values.next());
+        }
+
+        BiValue<Integer,String> found = null;
+        for(BiValue<Integer,String> each : test.asIterable()) {
+            if(0 == each.left()) {
+                found = each;
+                break;
+            }
+        }
+    }
+
+
+    public void testIsEmpty() {
+        assertFalse(test.isEmpty());
+        assertTrue(((MapStream<?,?>) Collections.emptyMap()).isEmpty());
+    }
+
+    public void testGetFirst() {
+        assertNotEquals(null, test.getFirst());
+        assertEquals(null, ((MapStream<?,?>) Collections.emptyMap()).getFirst());
+    }
+
+    public void testGetAny() {
+        assertNotEquals(null, test.getAny());
+        assertEquals(null, ((MapStream<?,?>) Collections.emptyMap()).getAny());
+    }
+
+    public void testGetOnlyGood() {
+        assertNotEquals(null, ((MapStream<String,String>) Collections.singletonMap("foo","bar")).getOnly());
+    }
+
+    @Test(expectedExceptions=IllegalStateException.class)
+    public void testGetOnlyBad() {
+        BiValue<Integer,String> notOnly = test.getOnly();
+    }
+
+    public void testLefts() {
+        Iterable<Integer> lefts = test.inputs();
+        Collection<Integer> leftInto = new ArrayList<>();
+        lefts.into(leftInto);
+
+        assertTrue(Arrays.asList(KEYS).containsAll(leftInto) &&
+                leftInto.containsAll(Arrays.asList(KEYS)));
+    }
+
+    public void testRights() {
+        Iterable<String> rights = test.values();
+
+        Collection<String> rightsInto = new ArrayList<>();
+        rights.into(rightsInto);
+
+        assertTrue(Arrays.asList(VALUES).containsAll(rightsInto) &&
+                rightsInto.containsAll(Arrays.asList(VALUES)));
+    }
+
+    public void testAsIterable() {
+        Iterable<? extends BiValue<Integer,String>> iterable = test.asIterable();
+
+        Set<BiValue<Integer,String>> into = new HashSet<>();
+        for(BiValue<Integer,String> element : iterable) {
+            into.add(element);
+        }
+
+        assertEquals(into, map.entrySet());
+    }
+
+    public void testAsMultiStream() {
+        MapStream<Integer, Iterable<String>> multi = test.asMultiStream();
+
+        List<BiValue<Integer, Iterable<String>>> into = new ArrayList<>();
+        for(BiValue<Integer,Iterable<String>> element : multi.asIterable()) {
+            into.add(element);
+        }
+
+        for(BiValue<Integer,Iterable<String>> pair : into) {
+            Integer key = pair.left();
+            Iterable<String> value = pair.right();
+
+            assertTrue(Arrays.asList(KEYS).contains(key));
+
+            List<String> forKey = new ArrayList<>();
+            value.into(forKey);
+
+            assertTrue(1 == forKey.size());
+            assertTrue(Arrays.asList(VALUES).contains(forKey.getFirst()));
+        }
+    }
+
+    public void testAllMatch() {
+        assertTrue(test.allMatch( (l,r) -> l >= 0), "should all be positive");
+        assertTrue(test.allMatch( (l,r) -> r.length() > 0), "should all be non-empty");
+    };
+
+    public void testNoneMatch() {
+        assertTrue(test.noneMatch( (l,r) -> l < 0), "should be no negatives");
+        assertTrue(test.noneMatch( (l,r) -> r.length() == 0), "should be no empty strings");
+    };
+
+    public void testAnyMatch() {
+        assertTrue(test.anyMatch( (l,r) -> l == 2), "there should be a '2'");
+        assertTrue(test.anyMatch( (l,r) -> "two".equals(r)),"there should be a 'two'");
+    };
+
+    public void testForEach() {
+        int heinous[] = new int[1];
+
+        test.forEach((l,r) -> {heinous[0]++;});
+        assertEquals(map.size(), heinous[0], "element count does not equal source size");
+    }
+
+    public void testFilter() {
+        Map<Integer, String> into = new HashMap<>();
+
+        test.filter((l,r) -> (l % 2) == 0).into(into);
+        assertTrue(into.size() == 2);
+        into.clear();
+        test.filter((l,r) -> "two".equals(r)).into(into);
+        assertTrue(into.size() == 1);
+    }
+
+    public void testFilterKeys() {
+        Map<Integer, String> into = new HashMap<>();
+
+        test.filterKeys(l -> l % 2 == 0).into(into);
+        assertTrue(into.size() == 2);
+    }
+
+    public void testFilterValues() {
+        Map<Integer, String> into = new HashMap<>();
+
+        test.filterValues(r -> "two".equals(r)).into(into);
+        assertTrue(into.size() == 1);
+    }
+
+    public void testMap() {
+        for(BiValue<Integer,String> each : test.map((l,r) -> l.toString()).asIterable()) {
+            assertEquals((int) each.left(), Integer.parseInt(each.right()), "values not equal");
+        }
+    }
+
+    public void testMapValues() {
+
+    }
+
+    public void testMapValuesMulti() {
+
+    }
+
+    public void testSorted() {
+        // standard order
+        int min = Integer.MIN_VALUE;
+        for(Integer each : test.sorted((one, two) -> one - two).inputs()) {
+            assertTrue(min <= each, "Not in ascending order");
+            min = each;
+        }
+
+        // reverse order
+        int max = Integer.MAX_VALUE;
+        for(Integer each : test.sorted((one, two) -> two - one).inputs()) {
+            assertTrue(max >= each, "Not in descending order");
+            max = each;
+        }
+    }
+}