jdk/test/java/util/Comparators/BasicTest.java
changeset 22461 6ed8434664ed
parent 22460 0273c023680c
parent 18733 2d3875b0d18b
child 22462 eed978e4169a
equal deleted inserted replaced
22460:0273c023680c 22461:6ed8434664ed
     1 /*
       
     2  * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 /*
       
    25  * @test
       
    26  * @bug 8001667 8010279
       
    27  * @run testng BasicTest
       
    28  */
       
    29 
       
    30 import java.util.Comparator;
       
    31 import java.util.Comparators;
       
    32 import java.util.AbstractMap;
       
    33 import java.util.Map;
       
    34 import org.testng.annotations.Test;
       
    35 
       
    36 import java.util.function.BinaryOperator;
       
    37 import java.util.function.Function;
       
    38 import java.util.function.ToIntFunction;
       
    39 import java.util.function.ToLongFunction;
       
    40 import java.util.function.ToDoubleFunction;
       
    41 
       
    42 import static org.testng.Assert.assertEquals;
       
    43 import static org.testng.Assert.assertTrue;
       
    44 import static org.testng.Assert.assertSame;
       
    45 import static org.testng.Assert.fail;
       
    46 
       
    47 /**
       
    48  * Unit tests for helper methods in Comparators
       
    49  */
       
    50 @Test(groups = "unit")
       
    51 public class BasicTest {
       
    52     private static class Thing {
       
    53         public final int intField;
       
    54         public final long longField;
       
    55         public final double doubleField;
       
    56         public final String stringField;
       
    57 
       
    58         private Thing(int intField, long longField, double doubleField, String stringField) {
       
    59             this.intField = intField;
       
    60             this.longField = longField;
       
    61             this.doubleField = doubleField;
       
    62             this.stringField = stringField;
       
    63         }
       
    64 
       
    65         public int getIntField() {
       
    66             return intField;
       
    67         }
       
    68 
       
    69         public long getLongField() {
       
    70             return longField;
       
    71         }
       
    72 
       
    73         public double getDoubleField() {
       
    74             return doubleField;
       
    75         }
       
    76 
       
    77         public String getStringField() {
       
    78             return stringField;
       
    79         }
       
    80     }
       
    81 
       
    82     private final int[] intValues = { -2, -2, -1, -1, 0, 0, 1, 1, 2, 2 };
       
    83     private final long[] longValues = { -2, -2, -1, -1, 0, 0, 1, 1, 2, 2 };
       
    84     private final double[] doubleValues = { -2, -2, -1, -1, 0, 0, 1, 1, 2, 2 };
       
    85     private final String[] stringValues = { "a", "a", "b", "b", "c", "c", "d", "d", "e", "e" };
       
    86     private final int[] comparisons = { 0, -1, 0, -1, 0, -1, 0, -1, 0 };
       
    87 
       
    88     private<T> void assertComparisons(T[] things, Comparator<T> comp, int[] comparisons) {
       
    89         for (int i=0; i<comparisons.length; i++) {
       
    90             assertEquals(comparisons.length + 1, things.length);
       
    91             assertEquals(comparisons[i], comp.compare(things[i], things[i+1]));
       
    92             assertEquals(-comparisons[i], comp.compare(things[i+1], things[i]));
       
    93         }
       
    94     }
       
    95 
       
    96     public void testIntComparator() {
       
    97         Thing[] things = new Thing[intValues.length];
       
    98         for (int i=0; i<intValues.length; i++)
       
    99             things[i] = new Thing(intValues[i], 0L, 0.0, null);
       
   100         Comparator<Thing> comp = Comparators.comparing(new ToIntFunction<BasicTest.Thing>() {
       
   101             @Override
       
   102             public int applyAsInt(Thing thing) {
       
   103                 return thing.getIntField();
       
   104             }
       
   105         });
       
   106 
       
   107         assertComparisons(things, comp, comparisons);
       
   108     }
       
   109 
       
   110     public void testLongComparator() {
       
   111         Thing[] things = new Thing[longValues.length];
       
   112         for (int i=0; i<longValues.length; i++)
       
   113             things[i] = new Thing(0, longValues[i], 0.0, null);
       
   114         Comparator<Thing> comp = Comparators.comparing(new ToLongFunction<BasicTest.Thing>() {
       
   115             @Override
       
   116             public long applyAsLong(Thing thing) {
       
   117                 return thing.getLongField();
       
   118             }
       
   119         });
       
   120 
       
   121         assertComparisons(things, comp, comparisons);
       
   122     }
       
   123 
       
   124     public void testDoubleComparator() {
       
   125         Thing[] things = new Thing[doubleValues.length];
       
   126         for (int i=0; i<doubleValues.length; i++)
       
   127             things[i] = new Thing(0, 0L, doubleValues[i], null);
       
   128         Comparator<Thing> comp = Comparators.comparing(new ToDoubleFunction<BasicTest.Thing>() {
       
   129             @Override
       
   130             public double applyAsDouble(Thing thing) {
       
   131                 return thing.getDoubleField();
       
   132             }
       
   133         });
       
   134 
       
   135         assertComparisons(things, comp, comparisons);
       
   136     }
       
   137 
       
   138     public void testComparing() {
       
   139         Thing[] things = new Thing[doubleValues.length];
       
   140         for (int i=0; i<doubleValues.length; i++)
       
   141             things[i] = new Thing(0, 0L, 0.0, stringValues[i]);
       
   142         Comparator<Thing> comp = Comparators.comparing(new Function<Thing, String>() {
       
   143             @Override
       
   144             public String apply(Thing thing) {
       
   145                 return thing.getStringField();
       
   146             }
       
   147         });
       
   148 
       
   149         assertComparisons(things, comp, comparisons);
       
   150     }
       
   151 
       
   152     public void testNaturalOrderComparator() {
       
   153         Comparator<String> comp = Comparators.naturalOrder();
       
   154 
       
   155         assertComparisons(stringValues, comp, comparisons);
       
   156     }
       
   157 
       
   158     public void testReverseComparator() {
       
   159         Comparator<String> cmpr = Comparators.reverseOrder();
       
   160         Comparator<String> cmp = cmpr.reverseOrder();
       
   161 
       
   162         assertEquals(cmp.reverseOrder(), cmpr);
       
   163         assertEquals(0, cmp.compare("a", "a"));
       
   164         assertEquals(0, cmpr.compare("a", "a"));
       
   165         assertTrue(cmp.compare("a", "b") < 0);
       
   166         assertTrue(cmpr.compare("a", "b") > 0);
       
   167         assertTrue(cmp.compare("b", "a") > 0);
       
   168         assertTrue(cmpr.compare("b", "a") < 0);
       
   169     }
       
   170 
       
   171     public void testReverseComparator2() {
       
   172         Comparator<String> cmp = (s1, s2) -> s1.length() - s2.length();
       
   173         Comparator<String> cmpr = cmp.reverseOrder();
       
   174 
       
   175         assertEquals(cmpr.reverseOrder(), cmp);
       
   176         assertEquals(0, cmp.compare("abc", "def"));
       
   177         assertEquals(0, cmpr.compare("abc", "def"));
       
   178         assertTrue(cmp.compare("abcd", "def") > 0);
       
   179         assertTrue(cmpr.compare("abcd", "def") < 0);
       
   180         assertTrue(cmp.compare("abc", "defg") < 0);
       
   181         assertTrue(cmpr.compare("abc", "defg") > 0);
       
   182     }
       
   183 
       
   184     @Test(expectedExceptions=NullPointerException.class)
       
   185     public void testReverseComparatorNPE() {
       
   186         Comparator<String> cmp = Comparators.reverseOrder(null);
       
   187     }
       
   188 
       
   189     public void testComposeComparator() {
       
   190         // Longer string in front
       
   191         Comparator<String> first = (s1, s2) -> s2.length() - s1.length();
       
   192         Comparator<String> second = Comparators.naturalOrder();
       
   193         Comparator<String> composed = Comparators.compose(first, second);
       
   194 
       
   195         assertTrue(composed.compare("abcdefg", "abcdef") < 0);
       
   196         assertTrue(composed.compare("abcdef", "abcdefg") > 0);
       
   197         assertTrue(composed.compare("abcdef", "abcdef") == 0);
       
   198         assertTrue(composed.compare("abcdef", "ghijkl") < 0);
       
   199         assertTrue(composed.compare("ghijkl", "abcdefg") > 0);
       
   200     }
       
   201 
       
   202     private <K, V> void assertPairComparison(K k1, V v1, K k2, V v2,
       
   203                                         Comparator<Map.Entry<K, V>> ck,
       
   204                                         Comparator<Map.Entry<K, V>> cv) {
       
   205         final Map.Entry<K, V> p11 = new AbstractMap.SimpleImmutableEntry<>(k1, v1);
       
   206         final Map.Entry<K, V> p12 = new AbstractMap.SimpleImmutableEntry<>(k1, v2);
       
   207         final Map.Entry<K, V> p21 = new AbstractMap.SimpleImmutableEntry<>(k2, v1);
       
   208         final Map.Entry<K, V> p22 = new AbstractMap.SimpleImmutableEntry<>(k2, v2);
       
   209 
       
   210         assertTrue(ck.compare(p11, p11) == 0);
       
   211         assertTrue(ck.compare(p12, p11) == 0);
       
   212         assertTrue(ck.compare(p11, p12) == 0);
       
   213         assertTrue(ck.compare(p12, p22) < 0);
       
   214         assertTrue(ck.compare(p12, p21) < 0);
       
   215         assertTrue(ck.compare(p21, p11) > 0);
       
   216         assertTrue(ck.compare(p21, p12) > 0);
       
   217 
       
   218         assertTrue(cv.compare(p11, p11) == 0);
       
   219         assertTrue(cv.compare(p12, p11) > 0);
       
   220         assertTrue(cv.compare(p11, p12) < 0);
       
   221         assertTrue(cv.compare(p12, p22) == 0);
       
   222         assertTrue(cv.compare(p12, p21) > 0);
       
   223         assertTrue(cv.compare(p21, p11) == 0);
       
   224         assertTrue(cv.compare(p21, p12) < 0);
       
   225 
       
   226         Comparator<Map.Entry<K, V>> cmp = Comparators.compose(ck, cv);
       
   227         assertTrue(cmp.compare(p11, p11) == 0);
       
   228         assertTrue(cmp.compare(p12, p11) > 0);
       
   229         assertTrue(cmp.compare(p11, p12) < 0);
       
   230         assertTrue(cmp.compare(p12, p22) < 0);
       
   231         assertTrue(cmp.compare(p12, p21) < 0);
       
   232         assertTrue(cmp.compare(p21, p11) > 0);
       
   233         assertTrue(cmp.compare(p21, p12) > 0);
       
   234 
       
   235         cmp = Comparators.compose(cv, ck);
       
   236         assertTrue(cmp.compare(p11, p11) == 0);
       
   237         assertTrue(cmp.compare(p12, p11) > 0);
       
   238         assertTrue(cmp.compare(p11, p12) < 0);
       
   239         assertTrue(cmp.compare(p12, p22) < 0);
       
   240         assertTrue(cmp.compare(p12, p21) > 0);
       
   241         assertTrue(cmp.compare(p21, p11) > 0);
       
   242         assertTrue(cmp.compare(p21, p12) < 0);
       
   243     }
       
   244 
       
   245     public void testKVComparatorable() {
       
   246         assertPairComparison(1, "ABC", 2, "XYZ",
       
   247                          Comparators.<Integer, String>naturalOrderKeys(),
       
   248                          Comparators.<Integer, String>naturalOrderValues());
       
   249     }
       
   250 
       
   251     private static class People {
       
   252         final String firstName;
       
   253         final String lastName;
       
   254         final int age;
       
   255 
       
   256         People(String first, String last, int age) {
       
   257             firstName = first;
       
   258             lastName = last;
       
   259             this.age = age;
       
   260         }
       
   261 
       
   262         String getFirstName() { return firstName; }
       
   263         String getLastName() { return lastName; }
       
   264         int getAge() { return age; }
       
   265         long getAgeAsLong() { return (long) age; };
       
   266         double getAgeAsDouble() { return (double) age; };
       
   267     }
       
   268 
       
   269     private final People people[] = {
       
   270         new People("John", "Doe", 34),
       
   271         new People("Mary", "Doe", 30),
       
   272         new People("Maria", "Doe", 14),
       
   273         new People("Jonah", "Doe", 10),
       
   274         new People("John", "Cook", 54),
       
   275         new People("Mary", "Cook", 50),
       
   276     };
       
   277 
       
   278     public void testKVComparators() {
       
   279         // Comparator<People> cmp = Comparators.naturalOrder(); // Should fail to compiler as People is not comparable
       
   280         // We can use simple comparator, but those have been tested above.
       
   281         // Thus choose to do compose for some level of interation.
       
   282         Comparator<People> cmp1 = Comparators.comparing((Function<People, String>) People::getFirstName);
       
   283         Comparator<People> cmp2 = Comparators.comparing((Function<People, String>) People::getLastName);
       
   284         Comparator<People> cmp = Comparators.compose(cmp1, cmp2);
       
   285 
       
   286         assertPairComparison(people[0], people[0], people[1], people[1],
       
   287                          Comparators.<People, People>byKey(cmp),
       
   288                          Comparators.<People, People>byValue(cmp));
       
   289 
       
   290     }
       
   291 
       
   292     private <T> void assertComparison(Comparator<T> cmp, T less, T greater) {
       
   293         assertTrue(cmp.compare(less, greater) < 0, "less");
       
   294         assertTrue(cmp.compare(less, less) == 0, "equal");
       
   295         assertTrue(cmp.compare(greater, less) > 0, "greater");
       
   296     }
       
   297 
       
   298     public void testComparatorDefaultMethods() {
       
   299         Comparator<People> cmp = Comparators.comparing((Function<People, String>) People::getFirstName);
       
   300         Comparator<People> cmp2 = Comparators.comparing((Function<People, String>) People::getLastName);
       
   301         // reverseOrder
       
   302         assertComparison(cmp.reverseOrder(), people[1], people[0]);
       
   303         // thenComparing(Comparator)
       
   304         assertComparison(cmp.thenComparing(cmp2), people[0], people[1]);
       
   305         assertComparison(cmp.thenComparing(cmp2), people[4], people[0]);
       
   306         // thenComparing(Function)
       
   307         assertComparison(cmp.thenComparing(People::getLastName), people[0], people[1]);
       
   308         assertComparison(cmp.thenComparing(People::getLastName), people[4], people[0]);
       
   309         // thenComparing(ToIntFunction)
       
   310         assertComparison(cmp.thenComparing(People::getAge), people[0], people[1]);
       
   311         assertComparison(cmp.thenComparing(People::getAge), people[1], people[5]);
       
   312         // thenComparing(ToLongFunction)
       
   313         assertComparison(cmp.thenComparing(People::getAgeAsLong), people[0], people[1]);
       
   314         assertComparison(cmp.thenComparing(People::getAgeAsLong), people[1], people[5]);
       
   315         // thenComparing(ToDoubleFunction)
       
   316         assertComparison(cmp.thenComparing(People::getAgeAsDouble), people[0], people[1]);
       
   317         assertComparison(cmp.thenComparing(People::getAgeAsDouble), people[1], people[5]);
       
   318     }
       
   319 
       
   320     public void testGreaterOf() {
       
   321         // lesser
       
   322         assertSame(Comparators.greaterOf(Comparators.comparing(
       
   323                                     (Function<People, String>) People::getFirstName))
       
   324                               .apply(people[0], people[1]),
       
   325                    people[1]);
       
   326         // euqal
       
   327         assertSame(Comparators.greaterOf(Comparators.comparing(
       
   328                                     (Function<People, String>) People::getLastName))
       
   329                               .apply(people[0], people[1]),
       
   330                    people[0]);
       
   331         // greater
       
   332         assertSame(Comparators.greaterOf(Comparators.comparing(
       
   333                                     (ToIntFunction<People>) People::getAge))
       
   334                               .apply(people[0], people[1]),
       
   335                    people[0]);
       
   336     }
       
   337 
       
   338     public void testLesserOf() {
       
   339         // lesser
       
   340         assertSame(Comparators.lesserOf(Comparators.comparing(
       
   341                                     (Function<People, String>) People::getFirstName))
       
   342                               .apply(people[0], people[1]),
       
   343                    people[0]);
       
   344         // euqal
       
   345         assertSame(Comparators.lesserOf(Comparators.comparing(
       
   346                                     (Function<People, String>) People::getLastName))
       
   347                               .apply(people[0], people[1]),
       
   348                    people[0]);
       
   349         // greater
       
   350         assertSame(Comparators.lesserOf(Comparators.comparing(
       
   351                                     (ToIntFunction<People>) People::getAge))
       
   352                               .apply(people[0], people[1]),
       
   353                    people[1]);
       
   354     }
       
   355 
       
   356     public void testNulls() {
       
   357         try {
       
   358             Comparators.<String>naturalOrder().compare("abc", (String) null);
       
   359             fail("expected NPE with naturalOrder");
       
   360         } catch (NullPointerException npe) {}
       
   361         try {
       
   362             Comparators.<String>naturalOrder().compare((String) null, "abc");
       
   363             fail("expected NPE with naturalOrder");
       
   364         } catch (NullPointerException npe) {}
       
   365 
       
   366         try {
       
   367             Comparators.<String>reverseOrder().compare("abc", (String) null);
       
   368             fail("expected NPE with naturalOrder");
       
   369         } catch (NullPointerException npe) {}
       
   370         try {
       
   371             Comparators.<String>reverseOrder().compare((String) null, "abc");
       
   372             fail("expected NPE with naturalOrder");
       
   373         } catch (NullPointerException npe) {}
       
   374 
       
   375         try {
       
   376             Comparator<Map.Entry<String, String>> cmp = Comparators.byKey(null);
       
   377             fail("byKey(null) should throw NPE");
       
   378         } catch (NullPointerException npe) {}
       
   379 
       
   380         try {
       
   381             Comparator<Map.Entry<String, String>> cmp = Comparators.byValue(null);
       
   382             fail("byValue(null) should throw NPE");
       
   383         } catch (NullPointerException npe) {}
       
   384 
       
   385         try {
       
   386             Comparator<People> cmp = Comparators.comparing((Function<People, String>) null);
       
   387             fail("comparing(null) should throw NPE");
       
   388         } catch (NullPointerException npe) {}
       
   389         try {
       
   390             Comparator<People> cmp = Comparators.comparing((ToIntFunction<People>) null);
       
   391             fail("comparing(null) should throw NPE");
       
   392         } catch (NullPointerException npe) {}
       
   393         try {
       
   394             Comparator<People> cmp = Comparators.comparing((ToLongFunction<People>) null);
       
   395             fail("comparing(null) should throw NPE");
       
   396         } catch (NullPointerException npe) {}
       
   397         try {
       
   398             Comparator<People> cmp = Comparators.comparing((ToDoubleFunction<People>) null);
       
   399             fail("comparing(null) should throw NPE");
       
   400         } catch (NullPointerException npe) {}
       
   401 
       
   402         try {
       
   403             BinaryOperator<String> op = Comparators.lesserOf(null);
       
   404             fail("lesserOf(null) should throw NPE");
       
   405         } catch (NullPointerException npe) {}
       
   406 
       
   407         try {
       
   408             BinaryOperator<String> op = Comparators.greaterOf(null);
       
   409             fail("lesserOf(null) should throw NPE");
       
   410         } catch (NullPointerException npe) {}
       
   411     }
       
   412 }