概述
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; ;) 这样的用法,从而避免了大量的生成临时遍历器而影响效率