Guava:Ordering 排序工具

简介

排序器 Ordering 是 Guava流畅风格比较器 Comparator 的实现,它可以用来为构建复杂的比较器,以完成集合排序的功能。

从实现上说,Ordering 实例就是一个特殊的 Comparator 实例。Ordering 把很多基于 Comparator 的静态方法(如 Collections.max)包装为自己的实例方法(非静态方法),并且提供了链式调用方法,来定制和增强现有的比较器。

类方法说明

官方文档:Source code

方法名称 方法描述
allEqual()  返回一个Ordering,所有值的排序地位都是平等的,表明无排序。 将此排序传递给任何稳定排序算法都不会导致元素顺序发生变化。
arbitrary()  返回所有对象的任意顺序,即compare(a, b) == 0 就是 a == b (identity equality)。 本身的排序是没有任何含义,但是在VM的生命周期是一个常量。
binarySearch(List sortedList, T key)  已过时,请使用 Collections.binarySearch(List, Object, Comparator).
compare(T left, T right)  比较两个参数的顺序。
compound(Comparator secondaryComparator)  返回一个Ordering,传入比较器作为第二排序元素。
compound(Iterable> comparators)  返回一个Ordering,会根据传入比较器集合一次比较,直到找到一个非零的结果。
explicit(List valuesInOrder)  返回一个Ordering,根据他们出现在给定的列表的顺序比较对象
explicit(T leastValue, T... remainingValuesInOrder)  返回一个Ordering,比较对象根据它们的传入的顺序。
from(Comparator comparator) 
返回一个传入comparator实例的Ordering。
from(Ordering ordering)  已过时。 不需要使用它
greatestOf(Iterable iterable, int k)  根据Ordering对传入iterable由大到小排序,返回前K位的集合。
greatestOf(Iterator iterator, int k)  根据Ordering对传入iterable由大到小排序,返回前K位的集合。
immutableSortedCopy(Iterable elements)  返回一个不可变的集合,包含根据Ordering对传入元素排序后的所有元素。
isOrdered(Iterable iterable)  根据Ordering对传入iterable元素迭代,如果下一个元素大于或等于上一个元素,返回true。
isStrictlyOrdered(Iterable iterable)  根据Ordering对传入iterable元素迭代,如果下一个元素严格大于上一个元素,返回true。
leastOf(Iterable iterable, int k)  根据Ordering对传入iterable由小到大排序,返回前K位的集合。
leastOf(Iterator iterator, int k)  根据Ordering对传入iterable由小到大排序,返回前K位的集合。
lexicographical()  返回一个新的Ordering,通过相应的元素两两迭代,直到找到一个非零的结果。强加“字典顺序”。
max(E a, E b)  根据Ordering返回传入参数的最大值。
max(E a, E b, E c, E... rest)  根据Ordering返回传入参数的最大值。
max(Iterable iterable)  根据Ordering返回传入参数的最大值。
max(Iterator iterator)  根据Ordering返回传入参数的最大值。
min(E a, E b)  根据Ordering返回传入参数的最小值。
min(E a, E b, E c, E... rest)  根据Ordering返回传入参数的最小值。
min(Iterable iterable)  根据Ordering返回传入参数的最小值。
min(Iterator iterator)  根据Ordering返回传入参数的最小值。
natural()  对可排序类型做自然排序,如数字按大小,日期按先后排序
nullsFirst()  根据Ordering排序,null值放在最前面,并使用它来比较非空值。
nullsLast()  根据Ordering排序,null值放在最后面,并使用此排序来比较非空值。
onResultOf(Function function)  将传入function应用到每个元素上面,再通过Ordering进行排序。
Ordering reverse() 
返回与当前Ordering相反的排序。相当于 Collections.reverseOrder(Comparator)
 List sortedCopy(Iterable elements) 
返回一个可变的集合,包含根据Ordering对传入元素排序后的所有元素。
usingToString()  根据toString返回的字符串按照字典顺序排序。

 使用Demo

import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.google.common.primitives.Doubles;
import junit.framework.TestCase;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.*;
import static java.util.Arrays.asList;

/**
 * 排序
 */
public class OrderingTests extends TestCase {

    /**
     * 1、allEqual 允许有null
     */
    public void testAllEqual() {
        Ordering comparator = Ordering.allEqual();
        System.out.println(comparator.equals(comparator.reverse()));

        assertEquals(0, comparator.compare(null, null));
        assertEquals(0, comparator.compare(new Object(), new Object()));
        assertEquals(0, comparator.compare("apples", "oranges"));
        assertEquals("Ordering.allEqual()", comparator.toString());

        List strings = ImmutableList.of("b", "a", "d", "c");
        List sortedCopy = comparator.sortedCopy(strings);
        assertEquals(strings, sortedCopy);
        ImmutableList immutableSortedCopy = comparator.immutableSortedCopy(strings);
        assertEquals(strings, immutableSortedCopy);
    }

    /**
     * 2、natural 不能有null
     */
    public void testNatural() {
        Ordering comparator = Ordering.natural();
        try {
            comparator.compare(1, null);
            fail();
        } catch (NullPointerException expected) {
        }
        try {
            comparator.compare(null, 2);
            fail();
        } catch (NullPointerException expected) {
        }
        try {
            comparator.compare(null, null);
            fail();
        } catch (NullPointerException expected) {
        }
        assertEquals("Ordering.natural()", comparator.toString());
    }

    /**
     * 3、List集合 复杂排序示例
     */
    public void testComplicatedOrderingExample() {
        Ordering> example = Ordering.natural().nullsFirst().reverse().lexicographical().reverse().nullsLast();

        List list1 = Lists.newArrayList();
        List list2 = Lists.newArrayList(1);
        List list3 = Lists.newArrayList(1, 1);
        List list4 = Lists.newArrayList(1, 2);
        List list5 = Lists.newArrayList(1, null, 2);
        List list6 = Lists.newArrayList(2);

        Integer nullInt = null;
        List list7 = Lists.newArrayList(nullInt);
        List list8 = Lists.newArrayList(nullInt, nullInt);
        List> list = Lists.newArrayList(list1, list2, list3, list4, list5, list6, list7, list8, null);

        List> sorted = example.sortedCopy(list);

        /**
         * [null, null]
         * [null]
         * [1, null, 2]
         * [1, 1]
         * [1, 2]
         * [1]
         * [2]
         * []
         * null
         */
        sorted.forEach(System.out::println);
    }

    /**
     * 4、from 把给定的 Comparator 转化为排序器
     */
    public void testFrom() {
        // String.CASE_INSENSITIVE_ORDER 按照 ASCII 排序
        Ordering caseInsensitiveOrdering = Ordering.from(String.CASE_INSENSITIVE_ORDER);
        assertTrue(caseInsensitiveOrdering.compare("A", "a") == 0);
        assertTrue(caseInsensitiveOrdering.compare("a", "B") < 0);
        assertTrue(caseInsensitiveOrdering.compare("B", "a") > 0);

        ArrayList list = Lists.newArrayList("dehua", "abcdef", "ABCDEF", "rapido", "lbsse","lasse");
        List sortedCopy = caseInsensitiveOrdering.sortedCopy(list);
        sortedCopy.forEach(System.out::println);
    }

    /*
     * 5、explicit(ExplicitOrdering)返回一个Ordering,根据它们的传入的顺序比较对象。只能比较参数列表中存在的对象
     */
    public void testExplicit_none() {
        Comparator c = Ordering.explicit(Collections.emptyList());
        try {
            c.compare(0, 0);
        } catch (Exception e) {
//            e.printStackTrace();
        }
        assertEquals("Ordering.explicit([])", c.toString());
    }

    public void testExplicit_one() {
        Comparator c = Ordering.explicit(0);
        assertEquals(0, c.compare(0, 0));
        try {
            c.compare(0, 1);
            fail();
        } catch (Exception e) {
//            e.printStackTrace();
        }
        assertEquals("Ordering.explicit([0])", c.toString());
    }

    public void testExplicit_two() {
//        Comparator c = Ordering.explicit(42, 5);
//        assertEquals(0, c.compare(5, 5));
//        assertTrue(c.compare(5, 42) > 0);
//        assertTrue(c.compare(42, 5) < 0);

        Comparator c = Ordering.explicit(5, 10);
        assertEquals(0, c.compare(5, 5));
        assertTrue(c.compare(5, 10) < 0);
        assertTrue(c.compare(10, 5) > 0);
        try {
            c.compare(5, 9);
            fail();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

    public void testExplicit_three() {
        // explicit:根据传入对象的顺序排序
        Double first = 0.2;
        Double[] second = {0.1, 0.3, 0.5};
        List numbers = Lists.asList(first, second);

        //排序比较器:根据原始的大小排序
        Ordering peopleOrdering = new Ordering() {
            @Override
            public int compare(Double left, Double right) {
                return Doubles.compare(left, right);
            }
        };
        peopleOrdering.reverse().explicit(numbers).sortedCopy(numbers).forEach(System.out::println);//[ 0.2,0.1, 0.3, 0.5]
    }


    public void testExplicit_sortingExample() {
        Comparator c = Ordering.explicit(2, 8, 6, 1, 7, 5, 3, 4, 0, 9);
        List list = Arrays.asList(0, 3, 5, 6, 7, 8, 9);
        Collections.sort(list, c);

        // 8, 6, 7, 5, 3, 0, 9
        list.forEach(System.out::println);
    }

    /**
     * key重复异常
     */
    public void testExplicit_withDuplicates() {
        try {
            Ordering.explicit(1, 2, 3, 4, 2);
            fail();
        } catch (IllegalArgumentException expected) {
            expected.printStackTrace();
        }
    }


    /**
     * 6、arbitrary 返回所有对象的任意顺序
     */
    public void testArbitrary_withoutCollisions() {
        List list = Lists.newArrayList();
        for (int i = 0; i < 50; i++) {
            list.add(i);
        }

        Ordering arbitrary = Ordering.arbitrary();
        Collections.sort(list, arbitrary);

        list.forEach(System.out::println);

        assertEquals("Ordering.arbitrary()", arbitrary.toString());
    }

    /**
     * 7、usingToString
     * 按对象的字符串形式做字典排序 [lexicographical ordering]
     */
    public void testUsingToString() {
        Ordering ordering = Ordering.usingToString();
        assertEquals("Ordering.usingToString()", ordering.toString());

        List list = Lists.newArrayList("lasse", "jerry", "harry", "eva", "jhon", "neron");
        System.out.println("list:" + list);

        // 使用Comparable类型的自然顺序, 例如:整数从小到大,字符串是按字典顺序;
        Ordering naturalOrdering = Ordering.natural();

        // 使用toString()返回的字符串按字典顺序进行排序;
        Ordering usingToStringOrdering = Ordering.usingToString();

        // 返回一个所有对象的任意顺序
        Ordering arbitraryOrdering = Ordering.arbitrary();

        System.out.println("naturalOrdering:" + naturalOrdering.sortedCopy(list));
        System.out.println("usingToStringOrdering:" + usingToStringOrdering.sortedCopy(list));
        System.out.println("arbitraryOrdering:" + arbitraryOrdering.sortedCopy(list));
    }

    /**
     * 8、reverse 取返
     */
    public void testReverse() {
        List list = Lists.newArrayList("lasse", "jerry", "harry", "eva", "jhon", "neron");
        Collections.sort(list, Ordering.natural().reverse());

        list.forEach(System.out::println);
    }

    private enum StringLengthFunction implements Function {
        StringLength;

        @Override
        public Integer apply(String string) {
            return string.length();
        }
    }

    /**
     * 9、onResultOf 将传入function应用到每个元素上面,再通过Ordering进行排序。
     */
    public void testOnResultOf_1() {
        // 外部枚举函数
        Ordering ordering = Ordering.natural().onResultOf(StringLengthFunction.StringLength);
        assertTrue(ordering.compare("to", "be") == 0);
        assertTrue(ordering.compare("or", "not") < 0);
        assertTrue(ordering.compare("that", "to") > 0);
        assertEquals("Ordering.natural().onResultOf(StringLength)", ordering.toString());

        ArrayList list = Lists.newArrayList("lasse", "abcds", "ABCDEF", "rapido", "chengxumiao");
        ordering.sortedCopy(list).forEach(System.out::println);
    }

    public void testOnResultOf_2() {
        // 匿名内部类函数
        Ordering ordering = Ordering.natural().onResultOf(new Function() {
            @Override
            public Comparable apply(@Nullable String input) {
                return input.length();
            }
        });

        ArrayList list = Lists.newArrayList("lasse", "abcds", "ABCDEF", "rapido", "chengxumiao");
        ordering.sortedCopy(list).forEach(System.out::println);
    }

    public void testOnResultOf_3() {
        // lambda 表达式函数
        Ordering ordering = Ordering.natural().reverse().onResultOf(str -> str.length());
        ArrayList list = Lists.newArrayList("lasse", "abcds", "ABCDEF", "rapido", "chengxumiao");
        ordering.sortedCopy(list).forEach(System.out::println);
    }

    /**
     * 10、nullsFirst
     */
    public void testNullsFirst_NullsLast() {
        ArrayList list = Lists.newArrayList("lasse", null, "abcds", "ABCDEF", null, "rapido", "chengxumiao");
        Collections.sort(list, Ordering.natural().nullsFirst());
        list.forEach(System.out::println);

        Ordering.natural().nullsLast().sortedCopy(list).forEach(System.out::println);

    }

    /**
     * 11、NullsLast
     */
    public void testNullsLast() {
        ArrayList list = Lists.newArrayList("tingfeng", null, "abcds", "ABCDEF", null, "rapido", "chengxumiao");
        Ordering.natural().nullsLast().sortedCopy(list).forEach(System.out::println);
    }

    /**
     * 12、isOrdered 下一个元素大于或等于上一个元素,返回true
     */
    public void testIsOrdered() {
        Ordering ordering = Ordering.natural();

        assertFalse(ordering.isOrdered(asList(5, 3, 0, 9)));
        assertFalse(ordering.isOrdered(asList(0, 5, 3, 9)));

        assertTrue(ordering.isOrdered(asList(0, 3, 5, 9)));
        assertTrue(ordering.isOrdered(asList(0, 0, 3, 3)));
        assertTrue(ordering.isOrdered(asList(0, 3)));
        assertTrue(ordering.isOrdered(Collections.singleton(1)));
        assertTrue(ordering.isOrdered(Collections.emptyList()));
    }

    /**
     * 13、isStrictlyOrdered 下一个元素大于上一个元素,返回true
     */
    public void testIsStrictlyOrdered() {
        Ordering ordering = Ordering.natural();

        assertFalse(ordering.isStrictlyOrdered(asList(5, 3, 0, 9)));
        assertFalse(ordering.isStrictlyOrdered(asList(0, 5, 3, 9)));
        assertFalse(ordering.isStrictlyOrdered(asList(0, 0, 3, 3)));

        assertTrue(ordering.isStrictlyOrdered(asList(0, 3, 5, 9)));
        assertTrue(ordering.isStrictlyOrdered(asList(0, 3)));
        assertTrue(ordering.isStrictlyOrdered(Collections.singleton(1)));
        assertTrue(ordering.isStrictlyOrdered(Collections.emptyList()));
    }


    /**
     * 判断集合是否只读
     */
    private static void assertListImmutable(List result) {
        try {
            result.set(0, 1);
            fail();
        } catch (UnsupportedOperationException expected) {
            // pass
        }
    }

    /**
     * 14、leastOf 有点类似截取集合前几位的概念
     */
    public void testLeastOfIterable_simple_1() {
        List result = Ordering.natural().leastOf(Arrays.asList(3, 4, 5, -1), 2);
        assertTrue(result instanceof RandomAccess);
        assertListImmutable(result);
        assertEquals(ImmutableList.of(-1, 3), result);
    }

    public void testLeastOfIterator_simple_1() {
        List result = Ordering.natural().leastOf(Iterators.forArray(3, 4, 5, -1), 2);
        assertTrue(result instanceof RandomAccess);
        assertListImmutable(result);
        assertEquals(ImmutableList.of(-1, 3), result);
    }

    public void testLeastOfIterable_simple_nMinusOne_withNullElement() {
        List list = Arrays.asList(3, null, 5, -1);
        List result = Ordering.natural().nullsLast().leastOf(list, list.size() - 1);
        assertTrue(result instanceof RandomAccess);
        assertListImmutable(result);
        assertEquals(ImmutableList.of(-1, 3, 5), result);
    }

    /**
     * 15、min 和 max
     */
    public void testIteratorMinAndMax() {
        Ordering ordering = Ordering.natural();
        List ints = Lists.newArrayList(5, 3, 0, 9);
        assertEquals(9, (int) ordering.max(ints));
        assertEquals(0, (int) ordering.min(ints));

        assertEquals(9, (int) ordering.max(ints.iterator()));
        assertEquals(0, (int) ordering.min(ints.iterator()));

        assertEquals(9, (int) ordering.max(ints.listIterator()));
        assertEquals(0, (int) ordering.min(ints.listIterator()));

        // 当值相同时,返回第一个参数,此处a正确,b就不正确
        Integer a = new Integer(4);
        Integer b = new Integer(4);
        ints = Lists.newArrayList(a, b, b);
        assertSame(a, ordering.max(ints.iterator()));
        assertSame(a, ordering.min(ints.iterator()));
    }

    public void testIteratorMinExhaustsIterator() {
        List ints = Lists.newArrayList(9, 0, 3, 5);
        Iterator iterator = ints.iterator();
        assertEquals(0, (int) Ordering.natural().min(iterator));
        assertFalse(iterator.hasNext());
    }

    public void testIteratorMaxExhaustsIterator() {
        List ints = Lists.newArrayList(9, 0, 3, 5);
        Iterator iterator = ints.iterator();
        assertEquals(9, (int) Ordering.natural().max(iterator));
        assertFalse(iterator.hasNext());
    }

}

你可能感兴趣的:(Guava,常用,guava,数据结构)