/* * Copyright 2014 Goldman Sachs. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.gs.collections.impl.block.factory; import java.io.Serializable; import java.sql.Timestamp; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Comparator; import java.util.Date; import java.util.List; import com.gs.collections.api.block.SerializableComparator; import com.gs.collections.api.block.function.Function; import com.gs.collections.api.block.function.primitive.BooleanFunction; import com.gs.collections.api.block.function.primitive.ByteFunction; import com.gs.collections.api.block.function.primitive.CharFunction; import com.gs.collections.api.block.function.primitive.DoubleFunction; import com.gs.collections.api.block.function.primitive.FloatFunction; import com.gs.collections.api.block.function.primitive.IntFunction; import com.gs.collections.api.block.function.primitive.LongFunction; import com.gs.collections.api.block.function.primitive.ShortFunction; import com.gs.collections.api.list.MutableList; import com.gs.collections.api.tuple.Pair; import com.gs.collections.impl.list.Interval; import com.gs.collections.impl.list.mutable.FastList; import com.gs.collections.impl.test.Verify; import com.gs.collections.impl.test.domain.Person; import com.gs.collections.impl.tuple.Tuples; import org.junit.Assert; import org.junit.Test; import static com.gs.collections.impl.factory.Iterables.*; public class ComparatorsTest { @Test public void classIsNonInstantiable() { Verify.assertClassNonInstantiable(Comparators.class); } @Test public void naturalOrder() { MutableList<String> list = FastList.newListWith("1", "4", "2", "3"); Assert.assertEquals( FastList.newListWith("1", "2", "3", "4"), list.sortThis(Comparators.naturalOrder())); Verify.assertThrows(NullPointerException.class, () -> FastList.newListWith("1", "2", null, "4").sortThis(Comparators.naturalOrder())); } @Test public void reverseNaturalOrder() { MutableList<String> list = FastList.newListWith("1", "4", "2", "3"); Assert.assertEquals( FastList.newListWith("4", "3", "2", "1"), list.sortThis(Comparators.<String>reverseNaturalOrder())); } @Test public void reverse() { MutableList<String> list = FastList.newListWith("1", "4", "2", "3"); Assert.assertEquals( FastList.newListWith("4", "3", "2", "1"), list.sortThis(Comparators.reverse(String::compareTo))); Verify.assertThrows(NullPointerException.class, () -> Comparators.reverse(null)); } @Test public void safeNullsLow() { SerializableComparator<Integer> comparator = Comparators.safeNullsLow(Comparators.byFunction(Functions.getIntegerPassThru())); Assert.assertEquals(-1, comparator.compare(null, 1)); Assert.assertEquals(1, comparator.compare(1, null)); Assert.assertEquals(0, comparator.compare(null, null)); Assert.assertEquals(0, comparator.compare(1, 1)); } @Test public void byBooleanFunction() { SerializableComparator<Integer> comparator = Comparators.byBooleanFunction((BooleanFunction<Integer>) anObject -> anObject.intValue() % 2 == 0); Verify.assertPositive(comparator.compare(2, 1)); Verify.assertZero(comparator.compare(1, 1)); Verify.assertZero(comparator.compare(2, 2)); Verify.assertNegative(comparator.compare(1, 2)); } @Test public void byByteFunction() { this.assertScalarFunctionParameter(Comparators.byByteFunction((ByteFunction<Integer>) Integer::byteValue)); } @Test public void byCharFunction() { this.assertScalarFunctionParameter(Comparators.byCharFunction((CharFunction<Integer>) anObject -> (char) anObject.intValue())); } @Test public void byDoubleFunction() { this.assertScalarFunctionParameter(Comparators.byDoubleFunction((DoubleFunction<Integer>) Integer::doubleValue)); } @Test public void byFloatFunction() { this.assertScalarFunctionParameter(Comparators.byFloatFunction((FloatFunction<Integer>) Integer::floatValue)); } @Test public void byIntFunction() { this.assertScalarFunctionParameter(Comparators.byIntFunction((IntFunction<Integer>) Integer::intValue)); } @Test public void byLongFunction() { this.assertScalarFunctionParameter(Comparators.byLongFunction((LongFunction<Integer>) Integer::longValue)); } @Test public void byShortFunction() { this.assertScalarFunctionParameter(Comparators.byShortFunction((ShortFunction<Integer>) Integer::shortValue)); } private void assertScalarFunctionParameter(SerializableComparator<Integer> comparator) { Verify.assertPositive(comparator.compare(2, 1)); Verify.assertPositive(comparator.compare(-1, -2)); Verify.assertZero(comparator.compare(1, 1)); Verify.assertZero(comparator.compare(0, 0)); Verify.assertZero(comparator.compare(-1, -1)); Verify.assertNegative(comparator.compare(3, 5)); Verify.assertNegative(comparator.compare(-5, -3)); } @Test public void safeNullsHigh() { SerializableComparator<Integer> comparator = Comparators.safeNullsHigh(Comparators.byFunction(Functions.getIntegerPassThru())); Assert.assertEquals(1, comparator.compare(null, 1)); Assert.assertEquals(-1, comparator.compare(1, null)); Assert.assertEquals(0, comparator.compare(null, null)); Assert.assertEquals(0, comparator.compare(1, 1)); } @Test public void chainedComparator() { Verify.assertThrows(IllegalArgumentException.class, (Runnable) Comparators::chain); Comparator<Person> byName = Comparators.byFunction(Person.TO_FIRST); Comparator<Person> byAge = Comparators.byFunction(Person.TO_AGE); Person fred10 = new Person("Fred", "Smith", 10); Person jim10 = new Person("Jim", "Smith", 10); Person jim16 = new Person("Jim", "Smith", 16); Person sheila12 = new Person("Sheila", "Smith", 12); Person sheila14 = new Person("Sheila", "Smith", 14); MutableList<Person> people = mList(jim16, fred10, sheila14, sheila12, fred10, jim10); MutableList<Person> expectedNameThenAgeOrder = mList(fred10, fred10, jim10, jim16, sheila12, sheila14); MutableList<Person> expectedAgeThenNameOrder = mList(fred10, fred10, jim10, sheila12, sheila14, jim16); Verify.assertListsEqual(expectedNameThenAgeOrder, people.sortThis(Comparators.chain(byName, byAge))); Verify.assertListsEqual(expectedAgeThenNameOrder, people.sortThis(Comparators.chain(byAge, byName))); } @Test public void fromFunctions() { Person raab = new Person(null, "Raab", 0); Person white = new Person(null, "White", 0); Comparator<Person> personComparator = Comparators.fromFunctions(Person.TO_LAST); Verify.assertNegative(personComparator.compare(raab, white)); Verify.assertPositive(personComparator.compare(white, raab)); Verify.assertZero(personComparator.compare(raab, raab)); } @Test public void fromFunctionsWithTwoArgs() { Person raab = new Person("Don", "Raab", 0); Person white = new Person("Barry", "White", 0); Person manilow = new Person("Barry", "Manilow", 0); Comparator<Person> personComparator = Comparators.fromFunctions(Person.TO_FIRST, Person.TO_LAST); Verify.assertPositive(personComparator.compare(raab, white)); Verify.assertNegative(personComparator.compare(white, raab)); Verify.assertZero(personComparator.compare(raab, raab)); Verify.assertPositive(personComparator.compare(white, manilow)); Verify.assertNegative(personComparator.compare(manilow, white)); } @Test public void fromFunctionsWithThreeArgs() { Person raab = new Person("Don", "Raab", 21); Person white = new Person("Barry", "White", 16); Person manilow = new Person("Barry", "Manilow", 60); Person manilow2 = new Person("Barry", "Manilow", 61); Comparator<Person> personComparator = Comparators.fromFunctions(Person.TO_FIRST, Person.TO_LAST, Person.TO_AGE); Verify.assertPositive(personComparator.compare(raab, white)); Verify.assertNegative(personComparator.compare(white, raab)); Verify.assertZero(personComparator.compare(raab, raab)); Verify.assertPositive(personComparator.compare(white, manilow)); Verify.assertNegative(personComparator.compare(manilow, white)); Verify.assertNegative(personComparator.compare(manilow, manilow2)); Verify.assertPositive(personComparator.compare(manilow2, manilow)); } @Test public void descendingCollectionSizeCompare() { MutableList<List<Integer>> list = FastList.<List<Integer>>newListWith( Interval.oneTo(1), Interval.oneTo(3), Interval.oneTo(2)); list.sortThis(Comparators.descendingCollectionSizeComparator()); Assert.assertEquals( FastList.<MutableList<Integer>>newListWith( FastList.newListWith(1, 2, 3), FastList.newListWith(1, 2), FastList.newListWith(1)), list); } @Test public void ascendingCollectionSizeCompare() { MutableList<List<Integer>> list = FastList.<List<Integer>>newListWith( Interval.oneTo(1), Interval.oneTo(3), Interval.oneTo(2)); list.sortThis(Comparators.ascendingCollectionSizeComparator()); Assert.assertEquals( FastList.<MutableList<Integer>>newListWith( FastList.newListWith(1), FastList.newListWith(1, 2), FastList.newListWith(1, 2, 3)), list); } @Test public void nullSafeEquals() { Assert.assertTrue(Comparators.nullSafeEquals("Fred", "Fred")); Assert.assertTrue(Comparators.nullSafeEquals(null, null)); Assert.assertFalse(Comparators.nullSafeEquals("Fred", "Jim")); Assert.assertFalse(Comparators.nullSafeEquals("Fred", null)); Assert.assertFalse(Comparators.nullSafeEquals(null, "Jim")); } @Test public void nullSafeCompare() { Assert.assertEquals(0, Comparators.nullSafeCompare(null, null)); Assert.assertEquals(0, Comparators.nullSafeCompare("Sheila", "Sheila")); Assert.assertTrue(Comparators.nullSafeCompare("Fred", "Jim") < 0); Assert.assertTrue(Comparators.nullSafeCompare("Sheila", "Jim") > 0); Assert.assertEquals(1, Comparators.nullSafeCompare("Fred", null)); Assert.assertEquals(-1, Comparators.nullSafeCompare(null, "Jim")); } @Test public void byFirstOfPair() { MutableList<Pair<Integer, String>> list = FastList.newListWith(Tuples.pair(3, "B"), Tuples.pair(1, "C"), Tuples.pair(2, "A")); MutableList<Pair<Integer, String>> sorted = FastList.newListWith(Tuples.pair(1, "C"), Tuples.pair(2, "A"), Tuples.pair(3, "B")); Verify.assertListsEqual(sorted, list.sortThis(Comparators.byFirstOfPair(Integer::compareTo))); } @Test public void bySecondOfPair() { MutableList<Pair<Integer, String>> list = FastList.newListWith(Tuples.pair(3, "B"), Tuples.pair(1, "C"), Tuples.pair(2, "A")); MutableList<Pair<Integer, String>> sorted = FastList.newListWith(Tuples.pair(2, "A"), Tuples.pair(3, "B"), Tuples.pair(1, "C")); Verify.assertListsEqual(sorted, list.sortThis(Comparators.bySecondOfPair(String::compareTo))); } @Test public void specializedComparator() { OneOfEach february = new OneOfEach(Timestamp.valueOf("2004-02-12 22:20:30")); OneOfEach april = new OneOfEach(Timestamp.valueOf("2004-04-12 22:20:30")); OneOfEach december = new OneOfEach(Timestamp.valueOf("2004-12-12 22:20:30")); Comparator<OneOfEach> comparator = Comparators.byFunction(OneOfEach.TO_DATE_VALUE, new FancyDateComparator()); Assert.assertEquals( iList(april, december, february), iList(february, april, december).toSortedList(comparator)); } public static class OneOfEach { public static final Function<OneOfEach, Date> TO_DATE_VALUE = oneOfEach -> new Date(oneOfEach.dateValue.getTime()); private Date dateValue = Timestamp.valueOf("2004-12-12 22:20:30"); public OneOfEach(Date dateValue) { this.dateValue = new Date(dateValue.getTime()); } } public static class FancyDateComparator implements Comparator<Date>, Serializable { private static final String FANCY_DATE_FORMAT = "EEE, MMM d, ''yy"; private static final long serialVersionUID = 1L; private final DateFormat formatter = new SimpleDateFormat(FANCY_DATE_FORMAT); @Override public int compare(Date o1, Date o2) { String date1 = this.formatter.format(o1); String date2 = this.formatter.format(o2); return date1.compareTo(date2); } } }