# HashSet去重复,根据对象的属性

场景,我们有两个配置,一个和公共的clist,一个是私有的slist,里头的配置可能有重复的,比如

  • 公共配置 clist
    {"key":"baidu", "value":"http://www.baidu.com"}
    {"key":"baidu-map", "value":"https://map.baidu.com/"}
    {"key":"taobao", "value":"http://www.taobao.com"}
    {"key":"jingdong", "value":"http://www.jd.com"}

  • 私有配置 slist
    {"key":"baidu", "value":"http://www.baidu.com/?query=test"} {"key":"baidu-map", "value":"https://map.baidu.com/sz/"}

最后我们需要的数据是slist+clist返回给前段。私有有先取私有,再取公共

分析,这个时候我们可以用for循环遍历,然后通过a.key.equals(b.key)去做!额,也不是不可以,但是不够好!这时候我想到Set去处理,HashSet的特点是里面的数据可以保证不重复。

回顾

  1. Set取值是根据本身取,所以不能重复,如果重复了,根据值去取的时候就会不知道取哪一个
  2. Map是根据具体key取值
  3. List是根据下标取值

HashSet里添加数据的时候,首先计算hash值int hash = hash(key)
hash值也就是存储位置
然后判断这个位置上是否有数据
如果没有,直接添加进去
如果有的话说明这俩数据hash值一样
然后用equals判断是否为true,如果为true则说明元素已经存在,如为false则插入元素。

当你把对象加入 HashSet 时,HashSet 会先计算对象的 hashCode 值来判断对象加入的位置,同时也会与其他已经加入的对象的 hashCode 值作比较,如果没有相符的 hashCode,HashSet 会假设对象没有重复出现。但是如果发现有相同 hashCode 值的对象,这时会调用 equals() 方法来检查 hashCode 相等的对象是否真的相同。如果两者相同,HashSet 就不会让其加入操作成功。如果不同的话,就会重新散列到其他位置。。这样我们就大大减少了 equals 的次数,相应就大大提高了执行速度。

去重实现

  1. clist和slist构建成Java对象
        //公共配置cList
        List<Item> cList = new ArrayList<>(Arrays.asList(
                new Item("baidu", "http://www.baidu.com"),
                new Item("baidu-map", "https://map.baidu.com/"),
                new Item("taobao", "http://www.taobao.com"),
                new Item("jingdong", "http://www.jd.com")
        ));

        //私有配置sList
        List<Item> sList = new ArrayList<>(Arrays.asList(
                new Item("baidu", "http://www.baidu.com/?query=test"),
                new Item("baidu-map", "https://map.baidu.com/sz/"),
                new Item("biubiu", "https://baijq.gitee.io/note/")
        ));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  1. 需要的数据是slist+clist返回给前段。私有有先取私有,再取公共

注意,对象放集合里的时候需要重写hashCodeequals

public class Item {
    private String key;
    private String value;

    public Item(String key, String value) {
        this.key = key;
        this.value = value;
    }
    //重写的时候只通过key去比较
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Item item = (Item) o;
        return Objects.equals(key, item.key);
    }
    //同理只通过key去计算hash
    @Override
    public int hashCode() {
        return Objects.hash(key);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

接下来直接丢HashSet里,自动去重

        Set<Item> set = new HashSet<>(sList);
        set.addAll(sList);
        set.addAll(cList);
1
2
3

结果如下,完成要求

[Item{key='taobao', value='http://www.taobao.com'}, Item{key='jingdong', value='http://www.jd.com'}, Item{key='biubiu', value='https://baijq.gitee.io/note/'}, Item{key='baidu-map', value='https://map.baidu.com/sz/'}, Item{key='baidu', value='http://www.baidu.com/?query=test'}]