欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

list去重

程序员文章站 2022-05-23 21:05:08
...

List数据去重在开发中是十分常见的场景,下面为大家介绍一个简单的方法:利用Set去重,但根据存储元素的不同,可以分为以下两类:

 

1. List中存储的是基本数据类型

下面看一段示例代码:

public class Test {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c", "d", "a", "b"));
        System.out.println(list);// 输出结果:[a, b, c, d, a, b]
        Set<String> set = new HashSet<>(list);
        List<String> newList = new ArrayList<>(set);
        System.out.println(newList);// 输出结果:[a, b, c, d]
    }
}
————————————————
原文链接:https://blog.csdn.net/weixin_40328662/article/details/99843102

 

 

2. List中存储的是对象类型

示例代码:

 

public class Test {
    public static void main(String[] args) {
        List<People> peopleList = new ArrayList<>();
        peopleList.add(new People("Joey", "001"));
        peopleList.add(new People("Joey", "001"));
        peopleList.add(new People("Johnny", "002"));
        peopleList.add(new People("Route", "003"));
        peopleList.add(new People("Vans", "004"));
        Set<People> peopleSet = new HashSet<>(peopleList);
        System.out.println(peopleSet);
    }
}
 
public class People {
 
    private String name;
    private String addrNum;
 
    // 省略无参、有参构造器,get、set方法,toString方法
 
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null || this.getClass() != obj.getClass()) {
            return false;
        }
        People people = (People) obj;
        return Objects.equals(name, people.name)
                && Objects.equals(addrNum, people.addrNum);
    }
 
    @Override
    public int hashCode() {
        return Objects.hash(name, addrNum);
    }
}
————————————————

原文链接:https://blog.csdn.net/weixin_40328662/article/details/99843102

 

 

如果List中存储的是对象类型,要想利用Set去重,就必须重写存储对象的equals()和hashCode()方法,为什么呢?

 

原因其实很简单,如下所示,HashSet的实现其实是HashMap,而HashMap中,通过key区分不同元素,key的比较顺序第一步就是计算对象的hashCode,看是否存在,第二步查找对应hashCode位置的对象是否与当前对象相等。这就需要用到hashCode()与equals()方法,equals()方法的默认实现是 ==,对于对象而言,比较的是内存中的地址。上述示例中,其实我们想要的效果是name与addrNum相等即视为同一个对象,但new的操作在堆中都是开辟新的内存空间,故两个对象的地址不一致,所以,我们必须覆写这两个方法

 

/**

 * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has

 * default initial capacity (16) and load factor (0.75).

 */

public HashSet() {

    map = new HashMap<>();

}

 

/**

 * Object类中equlas的默认实现

 */

public boolean equals(Object obj) {

    return (this == obj);

}

 

是不是非常简单,但可能有朋友会问,String并不属于基本数据类型,为什么也可以直接利用Set去重?其实,String类也重写了equals()和hashCode()方法,感兴趣的朋友可以去查看相关源码

 

总结:

利用HashSet去重,本质是利用了HashMap去重原理,Map/Set的key为自定义对象时,必须重写hashCode和equals

 

遵循如下规则(来自阿里巴巴Java开发手册):

 

1. 只要重写equals,就必须重写hashCode

 

2. 因为set存储的是不重复的对象,依据hashCode和equals进行判断,所以set存储的对象必须重写这两个方法

 

3. 如果自定义对象作为Map的键,那么必须重写hashCode和equals

————————————————

原文链接:https://blog.csdn.net/weixin_40328662/article/details/99843102