概述

CompoundOrdering是Ordering的子类,它用来存储比较器链, Ordering的compound()内部实现就是使用

CompoundOrdering(Comparator<? super T> primary,
                     Comparator<? super T> secondary)

方法来实现的

 

代码

/** An ordering that tries several comparators in order. */
@GwtCompatible(serializable = true)
final class CompoundOrdering<T> extends Ordering<T> implements Serializable {
    final ImmutableList<Comparator<? super T>> comparators;

    /**
     * 使用两个比较器组合成一个Ordering
     *
     * @param primary
     * @param secondary
     */
    CompoundOrdering(Comparator<? super T> primary,
                     Comparator<? super T> secondary) {
        this.comparators
                = ImmutableList.<Comparator<? super T>>of(primary, secondary);
    }

    CompoundOrdering(Iterable<? extends Comparator<? super T>> comparators) {
        this.comparators = ImmutableList.copyOf(comparators);
    }

    /**
     * 递归并按顺序的调用各个比较器进行比较
     *
     * @param left
     * @param right
     * @return
     */
    @Override public int compare(T left, T right) {
        // Avoid using the Iterator to avoid generating garbage (issue 979).
        // 使用for而不是foreach模式可以避免foreach生成iterator,这样会在每个compare方法结束后造成GC
        // 而且这是一个递归调用方法,如果一个CompoundOrdering拥有n个比较器,调用一次compare就会生成n个
        // iterator,并造成n次垃圾回收
        int size = comparators.size();
        for (int i = 0; i < size; i++) {
            int result = comparators.get(i).compare(left, right);
            if (result != 0) {
                return result;
            }
        }
        return 0;
    }

    /**
     * CompoundOrdering的判等通过comparators来判断
     *
     * @param object
     * @return
     */
    @Override public boolean equals(Object object) {
        if (object == this) {
            return true;
        }
        if (object instanceof CompoundOrdering) {
            CompoundOrdering<?> that = (CompoundOrdering<?>) object;
            return this.comparators.equals(that.comparators);
        }
        return false;
    }

    @Override public int hashCode() {
        return comparators.hashCode();
    }

    @Override public String toString() {
        return "Ordering.compound(" + comparators + ")";
    }

    private static final long serialVersionUID = 0;
}

 

分析

CompoundOrdering对顺序组合Ordering的实现是使用一个ImmutableList来保存,

查看代码

        Ordering<String> ordering =
                Ordering.from(comparator1)
                        .compound(comparator2)
                        .compound(comparator3)
                        .compound(comparator4);

这个ImmutableList结构图如下

大概就是一个ImmutableList内会包含一个Ordering和一个Comparator/Ordering, 这样在调用compare方法的时候会使用for循环遍历这个List并递归的调用这些comparator的compare方法,这样就保证了对comparator的顺序调用.另外,值得注意的是compare中取消了遍历器的for写法,而是使用for(int i; ;) 这样的用法,从而避免了大量的生成临时遍历器而影响效率

 

posted on 2013-09-24 20:54  ZimZz  阅读(767)  评论(0编辑  收藏  举报