问:简单说说 Comparable 和 Comparator 的区别和场景?
答:Comparable 对实现它的每个类的对象进行整体排序,这个接口需要类本身去实现,若一个类实现了 Comparable 接口,实现 Comparable 接口的类的对象的 List 列表(或数组)可以通过 Collections.sort(或 Arrays.sort)进行排序,此外实现 Comparable 接口的类的对象可以用作有序映射(如TreeMap)中的键或有序集合(如TreeSet)中的元素而不需要指定比较器, 实现 Comparable 接口必须修改自身的类(即在自身类中实现接口中相应的方法),如果我们使用的类无法修改(如 SDK 中一个没有实现 Comparable 的类),我们又想排序,就得用到 Comparator 这个接口了(策略模式)。所以如果你正在编写一个值类,它具有非常明显的内在排序关系,比如按字母顺序、按数值顺序或者按年代顺序,那你就应该坚决考虑实现 Comparable 这个接口, 若一个类实现了 Comparable 接口就意味着该类支持排序,而 Comparator 是比较器,我们若需要控制某个类的次序,可以建立一个该类的比较器来进行排序。Comparable 比较固定,和一个具体类相绑定,而 Comparator 比较灵活,可以被用于各个需要比较功能的类使用,所以尽量推荐使用 Comparator 而不是 Comparable,因为这样可以保证单一职责原则。
问:简单说说 Collection 和 Collections 的区别?
答:java.util.Collection 是一个集合接口,它提供了对集合对象进行基本操作的通用接口方法,在 Java 类库中有很多具体的实现,意义是为各种具体的集合提供最大化的统一操作方式。 譬如 Collection 的实现类有 List、Set 等,List 的实现类有 LinkedList、ArrayList、Vector 等,Vector 的实现类有 Stack 等,不过切记 Map 是自立门户的,其提供了转换为 Collection 的方法,但是自己不是 Collection 的子类。
java.util.Collections 是一个包装类,它包含有各种有关集合操作的静态多态方法,此类构造 private 不能实例化,就像一个工具类,服务于 Java 的 Collection 框架,其提供的方法大概可以分为对容器接口对象进行操作类(查找和替换、排序和调整顺序、添加和修改)和返回一个容器接口对象类(适配器将其他类型的数据转换为容器接口对象、装饰器修饰一个给定容器接口对象增加某种性质)。
问:Collections.emptyList() 与 new ArrayList() 有什么区别?
答:相同点为都是 AbstractList 的子类,都可以序列化。区别为 Collections.emptyList() 返回一个不可变的 List,而new ArrayList() 返回的 List 是可变的。只有当确实需要返回一个不可变空 List 时才使用Collections.emptyList(),多次调用 Collections.emptyList() 只会返回同一个 List 实例,而多次调用 new ArrayList() 每次都会返回新的实例。对于 emptySet() 和 emptyMap() 等类似方法有同样的结论适用。具体说服力如下源码所示:
public static final <T> List<T> emptyList () {
return (List<T>) EMPTY_LIST;
}
//EmptyList为Collections的一个内部类,为不可变列表
public static final List EMPTY_LIST = new EmptyList<>();
因此如下代码会抛出 UnsupportedOperationException 异常:
public class Demo {
public static void main(String[] args) {
List<Integer> list = Collections.emptyList();
list.add(100);//不可修改
}
}
问:下面程序的运行结果是什么?为什么?
class Info implements Comparable<Info> {
public String name;
public int age;
public Info(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Info o) {
return o.name.compareTo(this.name);
}
@Override
public boolean equals(Object obj) {
return ((Info) obj).age == this.age;
}
}
public class Demo {
public static void main(String[] args) {
List<Info> list = new ArrayList<Info>();
list.add(new Info("珠海", 0756));
list.add(new Info("小渔村", 0756));
Collections.sort(list);
Info info = new Info("小渔村", 0756);
int index1 = list.indexOf(info);
int index2 = Collections.binarySearch(list, info);
System.out.println("index1=" + index1 + ", index2=" + index2);
}
}
答:这段代码的运行结果为 index1=0, index2=1。
因为集合中的元素必须做到 compareTo 与 equals 方法结果同步,由于 equals 判断的是元素是否相等,binarySearch 判断的是元素在排序中的位置是否相等,因为 indexof 是通过 equals 方法进行判断的,而 Collections.binarySearch 方法是依据 compareTo 方法进行判断的,所以结果不同。