面试题 Java Set

List和Set的区别?

List,Set都是继承自Collection接口。都是用来存储一组相同类型的元素的。
List特点:元素有放入顺序,元素可重复 。
有顺序,即先放入的元素排在前面。
Set特点:元素无放入顺序,元素不可重复。
无顺序,即先放入的元素不一定排在前面。不可重复,即相同元素在set中只会保留一份。所以,有些场景下,set可以用来去重。

注意:set在元素插入时是要有一定的方法来判断元素是否重复的。这个方法很重要,决定了set中可以保存哪些元素。

Set如何保证元素不重复?

在Java的Set体系中,根据实现方式不同主要分为两大类。HashSet和TreeSet。
1、TreeSet 是二叉树实现的,Treeset中的数据是自动排好序的,不允许放入null值
2、HashSet 是哈希表实现的,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,就如数据库中唯一约束
在HashSet中,基本的操作都是有HashMap底层实现的,因为HashSet底层是用HashMap存储数据的。当向HashSet中添加元素的时候,首先计算元素的hashcode值,然后通过扰动计算和按位与的方式计算出这个元素的存储位置,如果这个位置位空,就将元素添加进去;如果不为空,则用equals方法比较元素是否相等,相等就不添加,否则找一个空位添加。
TreeSet的底层是TreeMap的keySet(),而TreeMap是基于红黑树实现的,红黑树是一种平衡二叉查找树,它能保证任何一个节点的左右子树的高度差不会超过较矮的那棵的一倍。
TreeMap是按key排序的,元素在插入TreeSet时compareTo()方法要被调用,所以TreeSet中的元素要实现Comparable接口。TreeSet作为一种Set,它不允许出现重复元素。TreeSet是用compareTo()来判断重复元素的。

HashSet实现原理?

1.基于HashMap实现的,默认构造函数是构建一个初始容量为16,负载因子为0.75 的HashMap。封装了一个 HashMap 对象来存储所有的集合元素,所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。
2.当试图把某个类的对象当成 HashMap的 key,或试图将这个类的对象放入 HashSet 中保存时,重写该类的equals(Object obj)方法和 hashCode() 方法,而且这两个方法的返回值必须保持一致:当该类的两个的 hashCode() 返回值相同时,它们通过 equals() 方法比较也应该返回 true。
通常来说,所有参与计算 hashCode() 返回值的关键属性,都应该用于作为 equals() 比较的标准。
3.HashSet的其他操作都是基于HashMap的。

如何取到Set集合中的第一个元素 ?

  1. public static void main(String[] args) {
  2. Set set = new HashSet();
  3. set.add("tracy");
  4. set.add("hcx");
  5. set.add(123);
  6. set.add(4.5);
  7. System.out.println(set);//[4.5, hcx, tracy, 123]
  8. //第一种方法
  9. if(!set.isEmpty()){
  10. System.out.println(set.iterator().next());// 4.5
  11. }
  12. //第二种方法:将set集合转换成list集合 取第一个
  13. List list = new ArrayList(set);
  14. System.out.println(list.get(0));// 4.5
  15. }

TreeMap和TreeSet在排序时如何比较元素?

TreeSet要求存放的对象所属的类必须是实现Comparable接口,该接口提供了比较元素的compareTo方法,当插入元素时会调该方法比较元素的大小.TreeMap要求存放的键值对映射的键必须实现Comparable接口,从而根据键对元素进行排序。

Collection工具类中的sort方法如何比较元素?

Collections工具类的sort方法有两种重载的形式,
第一种要求传入的待排序容器中存放的对象比较实现Comparable接口以实现元素的比较,
第二种不强制性的要求容器中的元素必须可比较但是要求第二个参数,参数是Comparator接口的子类型(需要重写compare方法实现元素的比较)相当一个临时定义的排序规则,其实就是通过接口注入比较元素大小的算法,也是对回调模式的应用。