[Guava源码分析]Ordering:排序

我的技术博客经常被流氓网站恶意爬取转载。请移步原文:http://www.cnblogs.com/hamhog/p/3876466.html,享受整齐的排版、有效的链接、正确的代码缩进、更好的阅读体验。

API

实例化

直接获得 natural() 自然序
usingToString() 字典序
指定 from(Comparator) 包装Comparator
explicit(List) explicit(least, ... others) 指明这几个东西的顺序,只排它们
直接继承  
其他 allEqual() 全相等。(稳定排序中)保持原序,可用来把null置后等
arbitrary() 任意序,似乎没什么意义。对VM周期是不变的。

继承写法:

 

Ordering<String> byLengthOrdering = new Ordering<String>() {
    public int compare(String left, String right) {
        return Ints.compare(left.length(), right.length());
    }
};

allEqual用法:

Ordering.allEqual().nullsLast().asList(t, null, e, s, null, t, null)); 
//return [t, e, s, t, null, null, null]

修饰方法

链式调用

reverse()  
nullsFirst()  
nullsLast()  
onResultOf(Function) 先应用Function
lexicographical()  类“字典序”,对于Iterable一位一位比下去

 

BreakTie

compound(Comparator)
compound(Iterable comparators)

 

应用

min(a,b) min(a,b,c, ...rest) min(Iterator) min(Iterable)   另有max
leastOf(Iterable, int k) leastOf(Iterator, int k) 最小的k个元素 另有greatestOf
sortedCopy(Iterable) 返回排好的List 另有immutableSortedCopy
isOrdered(Iterable) 判断是不是已经有序 另有isStrictlyOrdered

 

源码分析

1. 排序是怎么实现的?

natural

NaturalOrdering类
单例
compare() 直接调left.compareTo(right)
另见ReverseNaturalOrdering
以上两类reverse()方法互相转换。

toString

UsingToStringOrdering类
单例
compare()两者的toString

use comparator

ComparatorOrdering类
持有一个Comparator实例
compare()调Comparator

explicit

ExplicitOrdering类
持有一个rankMap
compare()以rank排序

others

AllEqualOrdering类
单例
compare()返回0

ArbitraryOrdering内部类
单例
compare()先比较Java给出的hashCode,如冲突用computingMap递增标记(1,2,3,4这样标下去)

2. 链式调用

典型的装饰模式,以下每个类都继承自Ordering,同时持有一个Ordering实例(大鱼吃小鱼,小鱼吃虾米)

Ordering<Foo> ordering = Ordering.natural().nullsFirst().onResultOf(sortKeyFunction)


先ByFunctionOrdering,调用sortKeyFunction.apply();然后NullsFirstOrdering,处理null;然后NaturalOrdering,调compareTo

ReverseOrdering类
compare()内层反向,逆转min、max

NullsFirstOrdering类
compare()先处理null,非null再调内层
另见NullsLastOrdering

ByFunctionOrdering类
持有Function
compare()先调function.apply(),用返回值排

LexicographicalOrdering类
compare()一位一位比过去,直到决出胜负或有一边断了

特殊:

CompoundOrdering类
持有一个Comparator List
compare()用List里的Comparator依次比较

不要把它跟别的链式调用写在一起。

3. 怎么找出最大/小的k个元素?

用到一个特殊算法。但如果要找的元素个数超过总数一半,则不用算法,而是直接排序截取,这样更快。算法适用于k远小n的情况。
算法流程:
保持一个2k大小的buffer;每次满了时,清掉较大的一半,剩下k位。
*剪枝优化:维护一个第k小的阈值,大于它的可以直接忽略了
*清掉一半的方法:快速选择。定一个标志位,比它小的挪到左边,比它大的挪到右边
时间O(n + k log k) 存储O(k)

posted @ 2014-07-29 20:54  戴仓薯  阅读(2299)  评论(0编辑  收藏  举报