Set和Map


Set集合

 Set是Collection下面的一个子接口。
 ?
 Set接口有以下特点:
     1. 无索引(不能根据索引获取元素的)
     2. 不可重复(不能保存重复元素)
     3. 无序的(大部分Set集合满足的特点)(按照什么顺序存,不一定按照什么顺序取)
 Set是一个接口,如果要用需要使用实现类,Set接口下最常用的实现类是HashSet
 HashSet满足Set接口的所有的特点(无序,无索引,不可重复)
 Set集合的遍历。
     因为Set集合是没有索引的,所以不能使用普通for遍历,可以使用迭代器或增强for遍历,强烈推荐增强for

01 哈希值

 哈希值其实就是一个int数字,我们可以将哈希值看成对象的一个标识(特征码)
 在Object中有一个方法叫做hashCode,可以获取对象的哈希值。
     int hashCode():获取对象的哈希值。
 ?
 Object中的hashCode方法,哈希值的计算方式是根据对象的地址值计算的。
 对象的哈希值根据地址值计算一般来说意义不大,我们更多的是希望哈希值是根据属性计算的,如果两个对象的属性完全相同,
 哈希值也应该相同。
 如果想要自己定义哈希值的计算规则,需要重写hashCode方法。
 哈希值是对象的一个标识,但并不是唯一的标识,对象的哈希值允许重复。
    //重写hashCode方法,自己定义哈希值的计算规则
     @Override
     public int hashCode() {
         return name.hashCode() * 31 + age;
     }

02 哈希表

哈希表是一个数组,数组中的每个元素是链表,哈希表可以提高查找效率

03 HashSe唯一性

HashSet判断唯一性的过程

先比较对象的哈希值。 如果哈希值不同,肯定是不同的对象。 如果哈希值相同,不一定是同一个对象。

如果哈希值相同,还会调用equals进行比较。 如果equals的结果是true,表示对象相同。 如果equals的结果是false,表示对象不同

结论: 如果使用HashSet存储自定义对象并保证唯一性(对象的属性相同就看成是同一个对象),需要同时重写hashCode和equals,缺一不可。

Map

Map集合不能通过迭代器或者增强for直接进行遍历。

Map集合有两种遍历方式 keySet方式(键找值)【推荐】 entrySet方式(键值对) 如果要遍历Map集合,我们可以获取到Map集合中所有的键,
将所有的键放入到Set集合中, 然后遍 历Set集合,拿到集合中的每一个键,然后根据键去Map集合中获取对应的值。 HashMap保证唯一性(键)的方式和HashSet是一模一样。 LinkedHashMap是Map接口下一个不常用的实现类,内部除了有一个哈希表之外还有一个链表,链表可以保证有序

Map计数器

map.put(key, map.containsKey(key) ? map.get(key) + 1 : 1);