8020156: TreeMap.values().spliterator() does not report ORDERED
authorpsandoz
Mon, 29 Jul 2013 19:41:02 +0100
changeset 19065 f7c941aa63ee
parent 19064 5a45b684b8b1
child 19066 daf668acb10e
8020156: TreeMap.values().spliterator() does not report ORDERED 8020009: TreeMap.entrySet().spliterator() reports SORTED + null comparator but the elements are not Comparable Reviewed-by: mduigou
jdk/src/share/classes/java/util/TreeMap.java
jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java
--- a/jdk/src/share/classes/java/util/TreeMap.java	Mon Jul 29 21:39:21 2013 +0530
+++ b/jdk/src/share/classes/java/util/TreeMap.java	Mon Jul 29 19:41:02 2013 +0100
@@ -25,6 +25,7 @@
 
 package java.util;
 
+import java.io.Serializable;
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 import java.util.function.Consumer;
@@ -2865,7 +2866,7 @@
         }
 
         public int characteristics() {
-            return (side == 0 ? Spliterator.SIZED : 0);
+            return (side == 0 ? Spliterator.SIZED : 0) | Spliterator.ORDERED;
         }
     }
 
@@ -2942,9 +2943,23 @@
         }
 
         @Override
-        public Comparator<? super Map.Entry<K, V>> getComparator() {
-            return tree.comparator != null ?
-                    Map.Entry.comparingByKey(tree.comparator) : null;
+        public Comparator<Map.Entry<K, V>> getComparator() {
+            // Since SORTED is reported and Map.Entry elements are not comparable
+            // then a non-null comparator needs to be returned
+            if (tree.comparator != null) {
+                // Adapt the existing non-null comparator to compare entries
+                // by key
+                return Map.Entry.comparingByKey(tree.comparator);
+            }
+            else {
+                // Return a comparator of entries by key, with K assumed to be
+                // of Comparable
+                return (Comparator<Map.Entry<K, V>> & Serializable) (e1, e2) -> {
+                    @SuppressWarnings("unchecked")
+                    Comparable<? super K> k1 = (Comparable<? super K>) e1.getKey();
+                    return k1.compareTo(e2.getKey());
+                };
+            }
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java	Mon Jul 29 19:41:02 2013 +0100
@@ -0,0 +1,147 @@
+/*
+ * 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
+ * @bug 8020156 8020009
+ * @run testng SpliteratorCharacteristics
+ */
+
+import org.testng.annotations.Test;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Spliterator;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import static org.testng.Assert.*;
+
+@Test
+public class SpliteratorCharacteristics {
+
+    public void testTreeMap() {
+        TreeMap<Integer, String> tm = new TreeMap<>();
+        tm.put(1, "4");
+        tm.put(2, "3");
+        tm.put(3, "2");
+        tm.put(4, "1");
+
+        assertCharacteristics(tm.keySet(),
+                              Spliterator.SIZED | Spliterator.DISTINCT |
+                              Spliterator.SORTED | Spliterator.ORDERED);
+        assertNullComparator(tm.keySet());
+
+        assertCharacteristics(tm.values(),
+                              Spliterator.SIZED | Spliterator.ORDERED);
+        assertISEComparator(tm.values());
+
+        assertCharacteristics(tm.entrySet(),
+                              Spliterator.SIZED | Spliterator.DISTINCT |
+                              Spliterator.SORTED | Spliterator.ORDERED);
+        assertNotNullComparator(tm.entrySet());
+    }
+
+    public void testTreeMapWithComparator() {
+        TreeMap<Integer, String> tm = new TreeMap<>(Comparator.<Integer>reverseOrder());
+        tm.put(1, "4");
+        tm.put(2, "3");
+        tm.put(3, "2");
+        tm.put(4, "1");
+
+        assertCharacteristics(tm.keySet(),
+                              Spliterator.SIZED | Spliterator.DISTINCT |
+                              Spliterator.SORTED | Spliterator.ORDERED);
+        assertNotNullComparator(tm.keySet());
+
+        assertCharacteristics(tm.values(),
+                              Spliterator.SIZED | Spliterator.ORDERED);
+        assertISEComparator(tm.values());
+
+        assertCharacteristics(tm.entrySet(),
+                              Spliterator.SIZED | Spliterator.DISTINCT |
+                              Spliterator.SORTED | Spliterator.ORDERED);
+        assertNotNullComparator(tm.entrySet());
+    }
+
+    public void testTreeSet() {
+        TreeSet<Integer> ts = new TreeSet<>();
+        ts.addAll(Arrays.asList(1, 2, 3, 4));
+
+        assertCharacteristics(ts,
+                              Spliterator.SIZED | Spliterator.DISTINCT |
+                              Spliterator.SORTED | Spliterator.ORDERED);
+        assertNullComparator(ts);
+    }
+
+    public void testTreeSetWithComparator() {
+        TreeSet<Integer> ts = new TreeSet<>(Comparator.reverseOrder());
+        ts.addAll(Arrays.asList(1, 2, 3, 4));
+
+        assertCharacteristics(ts,
+                              Spliterator.SIZED | Spliterator.DISTINCT |
+                              Spliterator.SORTED | Spliterator.ORDERED);
+        assertNotNullComparator(ts);
+    }
+
+
+    void assertCharacteristics(Collection<?> c, int expectedCharacteristics) {
+        assertCharacteristics(c.spliterator(), expectedCharacteristics);
+    }
+
+    void assertCharacteristics(Spliterator<?> s, int expectedCharacteristics) {
+        assertTrue(s.hasCharacteristics(expectedCharacteristics));
+    }
+
+    void assertNullComparator(Collection<?> c) {
+        assertNullComparator(c.spliterator());
+    }
+
+    void assertNullComparator(Spliterator<?> s) {
+        assertNull(s.getComparator());
+    }
+
+    void assertNotNullComparator(Collection<?> c) {
+        assertNotNullComparator(c.spliterator());
+    }
+
+    void assertNotNullComparator(Spliterator<?> s) {
+        assertNotNull(s.getComparator());
+    }
+
+    void assertISEComparator(Collection<?> c) {
+        assertISEComparator(c.spliterator());
+    }
+
+    void assertISEComparator(Spliterator<?> s) {
+        boolean caught = false;
+        try {
+            s.getComparator();
+        }
+        catch (IllegalStateException e) {
+            caught = true;
+        }
+        assertTrue(caught);
+    }
+}