VVL1295

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Comparable,Comparator

Comparable:

  类实现 Comparable 接口即可进行自然排序,排序是根据类所实现的 compareTo() 方法,小于,等于,大于的比较结果分别用负整数,0,正整数作为返回值表示;

  实现了 Comparable 的类可作为有序映射中的键或者有序集合中的元素,无需指定比较器(Comparator);

  comparaTo() 应该与 equals() 保持一致,即comparaTo(obj) 返回 0 的情况下,equals(obj) 需要返回 true,虽然不是必需;

  了解 compareTo() 方法:

    除了上述的要求,还有以下要求:

      1,确保如果 y.compareTo(x) 抛出异常,x.compareTo(y) 也要抛出异常;

      2,e.compareTo(null) 会抛出 NPE;

      3,实现类确保关系是可传递的:(x.compareTo(y)>0 && y.compareTo(z)>0) 意味着 x.compareTo(z)>0

      4,最后,实现者必须确保 x.compareTo(y)==0 意味着对于所有的 z,都存在 sgn(x.compareTo(z)) == sgn(y.compareTo(z))。 强烈推荐 (x.compareTo(y)==0) == (x.equals(y)) 这种做法,但并不是 严格要求这样做

    在前面的描述中,符号 sgn(expression) 指定 signum 数学函数,该函数根据 expression 的值是负数、零还是正数,分别返回 -101 中的一个值。 

    上代码:

 

public class Student implements Comparable<Student>{
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @SuppressWarnings("cast")
    @Override
    public int compareTo(Student student) {
        
        if (student == null) {
            throw new NullPointerException("compareTo 的对象不能为 null。");
        }
        if (!(student instanceof Student)) {
            throw new ClassCastException("compareTo 的对象必须是 Student 实例。");
        }
        
        int len1 = this.name.length();
        int len2 = student.name.length();
        if (len1 > len2) {
            return 1;
        }
        else if (len1 < len2) {
            return -1;
        }
        else {
            return 0;
        }
    }
    
}

 

 

 

Comparator:

  实现 Comparator 接口的类的实例,可以被传递到 sort 方法(如 Collections.sort 或 Arrays.sort),从而允许在排序顺序上实现精确控制;也可以使用 Comparator 来控制某些集合类实例的元素的顺序;

  实现 Comparator 接口需要实现 compare() 方法,实现该方法的要求与 compareTo() 方法一致;

  需要注意的是,TreeSet 判断元素重复,是通过调用 compare() 方法,通过其是否返回 0 进行判断,Set 的常规判断是通过 equals() 方法进行判断的;所以使用 Comparator 用在 TreeSet 上时,实现 compare() 方法需要注意,compare() 方法需要与 需要被排序的对象类型的 equals() 方法一致,这样就能同时符合 Set 的常规判断标准;

  上代码:

 

public class StringComparator implements Comparator<String>{

    @Override
    public int compare(String str1, String str2) {
        int len1 = str1.length();
        int len2 = str2.length();
        if (len1 > len2) {
            return 1;
        }
        else if (len1 < len2) {
            return -1;
        }
        else {
            return 0;
        }
    }
    
}

 

public class Test {
    
    public static void main(String[] args) {
        
        Set<String> set = new TreeSet<>(new StringComparator());
        set.add("000");
        set.add("0");
        set.add("000000");
        System.out.println(set);
    }
}
public class Test {
    
    public static void main(String[] args) {
        
        List<String> list = new ArrayList<>();
        
        list.add("000");
        list.add("0");
        list.add("000000");
        
        Collections.sort(list, new StringComparator());
        System.out.println(list);
    }
}

 

  虽然说建议 compareTo() compare() 方法与 equals() 方法保持一致,但有时为了实现某些业务逻辑,违反这个建议比较好,那只要在方法说明这个方法与 equals() 方法不一致即可;

 

  注意:Collections.sort() 方法,compare() 返回 -1,表示把 o1 排在 o2 前面;

以上。

posted on 2017-06-27 12:38  bobo2018  阅读(140)  评论(0)    收藏  举报