ConcurrentSkipListMap的自定义比较器

时间:2012-12-14 11:26:54

标签: java sorting map

我需要为ConcurrentSkipListMap定义一个自定义比较器,我使用此代码根据'LogicalClock'进行排序,但结果并不像我预期的那样。我创建了这样的密钥:“ClientId”+“:”+“LogicalClock”

class Qentry{
    int  AckCount;
    int ClientID; 
    long LogicalClock;
}

Comparator<String> LogicalClockComparator = new Comparator<String>() {
        @Override public int compare(String k1, String k2) {
            if  (k1.compareTo(k2)==0)
                    return 0;
            return   (int)( Long.valueOf(k1.substring(k1.indexOf(":")+1)) -Long.valueOf(k2.substring(k1.indexOf(":")+1) ));
        }
ConcurrentSkipListMap<String,Qentry> q;
q =new ConcurrentSkipListMap<String,Qentry>(LogicalClockComparator);

3 个答案:

答案 0 :(得分:2)

看起来像是一个错字(或复制/粘贴错误)给我,也许你想用(看看行尾)

return   (int)( Long.valueOf(k1.substring(k1.indexOf(":")+1)) -Long.valueOf(k2.substring(k2.indexOf(":")+1) ));

而不是你拥有的:

return   (int)( Long.valueOf(k1.substring(k1.indexOf(":")+1)) -Long.valueOf(k2.substring(k1.indexOf(":")+1) ));

答案 1 :(得分:1)

对于大的时间差异,这会产生令人惊讶的结果。 compare应该只返回-1,0或+1,但你可以使用更大的范围。对于long,您希望将溢出转换为int,这会产生意外行为。

我建议您使用Long.compare()(如果可用)和Double.compare(如果不可用)。

BTW,因为地图不允许重复键,当您返回0时,它会将其视为重复,因此如果您有a:1b:1c:1,则它们都是重复。解决这个问题的方法是在比较相等的情况下比较整个String。

BTW2虽然这是非常低效的代码,但您可以使用parseLong代替valueOf来稍微改进它。

答案 2 :(得分:1)

除了拼写错误之外,请注意您有两个潜在的溢出源:减去2个长点和转换为int时。最好使用:

Long value1 = Long.valueOf(k1.substring(k1.indexOf(":")+1));
Long value2 = Long.valueOf(k2.substring(k2.indexOf(":")+1));
return value1.compareTo(value2);