1、Compareable使用
通常某个类具有内在的排序规则,如按时间 长度等维度是可排序的话,建议实现Compareable接口,重写compareTo方式
这样的话存放数组或集合框架中时,我们可用Arrays.sort(x)或Collections.sort(x)按其自然顺序排序。
例子
import java.util.Objects; public class Model implements Comparable<Model>{ private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Model model = (Model) o; return age == model.age && Objects.equals(name, model.name); } @Override public int hashCode() { return Objects.hash(name, age); } @Override public int compareTo(Model o) { int result = name.compareTo(o.getName()); if(result == 0){ if(age<o.getAge()){ return -1; } if(age>o.getAge()){ return 1; }else{ return 0; } }else{ return result; } } }
2、重写compareTo原则
对于TreeSet TreeMap有序集合,判断某个对象是否存在是按Compareable接口来判断的。
所以当我们重写equals hashCode compareTo方法时,需要用相同的域来判断,这3者强烈建议保持一致。
否则如何两个对象obj1和obj2 obj1.equals(obj2)==true;而obj1.compareTo(obj2) != 0
此时如何存入TreeSet中就会当做两个不同的对象,容易产生迷惑。
代码:
import java.util.Objects; public class Model implements Comparable<Model>{ private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Model model = (Model) o; return age == model.age; } @Override public int hashCode() { return Objects.hash(age); } @Override public int compareTo(Model o) { int result = name.compareTo(o.getName()); if(result == 0){ if(age<o.getAge()){ return -1; } if(age>o.getAge()){ return 1; }else{ return 0; } }else{ return result; } } }
此对象按age来判断是否相等,而compareTo是按name和age来判断是否相等
测试存入TreeSet
public static void main(String[] args) throws IOException { Model model1 = new Model(); model1.setAge(12); model1.setName("xiaoming"); Model model12 = new Model(); model12.setAge(12); model12.setName("xiaoli"); TreeSet<Model> treeSet = new TreeSet<Model>(); treeSet.add(model1); treeSet.add(model12); System.out.println(treeSet.size()); }
执行返回:2
这样从语义上就很让人迷惑了!
3、与Comparator区别
Compareable是一个类必须实现此接口重写compareTo方法,在类的内部决定如何排序
而Comparator并不要求类一定要实现接口,它是一种额外的附件排序
上代码:
public static void main(String[] args) throws IOException { Model model1 = new Model(); model1.setAge(13); model1.setName("xiaoming"); Model model12 = new Model(); model12.setAge(12); model12.setName("xiaoli"); List<Model> modelList = new ArrayList<Model>(); modelList.add(model1); modelList.add(model12); Collections.sort(modelList, (o1, o2) -> { if(o1.getAge() < o2.getAge()){ return -1; } if(o1.getAge() > o2.getAge()){ return 1; }else{ return 0; } }); modelList.forEach(model -> System.out.println(model)); }
执行返回:
Model{name='xiaoli', age=12}
Model{name='xiaoming', age=13}
总结:
1、Comparable相当于“内部比较器”,而Comparator相当于“外部比较器”。
2、前者固定,后者灵活。后者可实现数据和比较逻辑分离
大多数情况个人建议Comparator接口外挂实现。