当前位置: 首页 / 技术干货 / 正文
Set接口简介

2022-12-15

元素 hashset student 集合

  Set接口简介

  Set接口和List接口一样,同样继承自Collection接口,它与Collection接口中的方法基本一致,并没有对Collection接口进行功能上的扩充,只是比Collection接口更加严格了。与List接口不同的是,Set接口中元素无序,并且都会以某种规则保证存入的元素不出现重复。

  Set接口主要有两个实现类,分别是HashSet和TreeSet。其中,HashSet是根据对象的哈希值来确定元素在集合中的存储位置,具有良好的存取和查找性能。TreeSet则是以二叉树的方式来存储元素,它可以实现对集合中的元素进行排序。

  HashSet集合

  HashSet是Set接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的。接下来通过一个案例演示HashSet集合的用法。  

Java
import java.util.HashSet;
import java.util.Iterator;

public class Example07 {
    public static void main(String[] args) {
        HashSet set = new HashSet(); // 创建HashSet集合
        set.add("张三"); // 向该Set集合中添加字符串
        set.add("李四");
        set.add("王五");
        set.add("李四"); // 向该Set集合中添加重复元素
        Iterator it = set.iterator(); // 获取Iterator对象
        while (it.hasNext()) { // 通过while循环,判断集合中是否有元素
            Object obj = it.next(); // 如果有元素,就通过迭代器的next()方法获取元素
            System.out.println(obj);
        }
    }
}

  从打印结果可以看出,取出元素的顺序与添加元素的顺序并不一致,并且重复存入的字符串对象“李四”被去除了,只添加了一次。

  HashSet集合之所以能确保不出现重复的元素,是因为它在存入元素时做了很多工作。当调用HashSet集合的add()方法存入元素时,首先调用当前存入对象的hashCode()方法获得对象的哈希值,然后根据对象的哈希值计算出一个存储位置。如果该位置上没有元素,则直接将元素存入,如果该位置上有元素存在,则会调用equals()方法让当前存入的元素依次和该位置上的元素进行比较,如果返回的结果为false就将该元素存入集合,返回的结果为true则说明有重复元素,就将该元素舍弃。HashSet存储元素的流程如下图所示。

  根据前面的分析不难看出,当向集合中存入元素时,为了保证HashSet正常工作,要求在存入对象时,重写Object类中的hashCode()和equals()方法。在上述案例中将字符串存入HashSet时,String类已经重写了Object类中的hashCode()和equals()方法。但是如果将自定义的Student对象存入HashSet,结果又如何呢?

  接下来通过一个案例演示向HashSet存储字符串。 

Java
import java.util.HashSet;

class Student {
    String id;
    String name;

          // 创建构造方法
    public Student(String id, String name) {
        this.id = id;
        this.name = name;
    }

          // 重写toString()方法
    @Override
    public String toString() {
        return id + ":" + name;
    }
}
public class Example08 {
    public static void main(String[] args) {
        HashSet hs = new HashSet(); // 创建HashSet集合
        Student stu1 = new Student("1", "张三"); // 创建Student对象
        Student stu2 = new Student("2", "李四");
        Student stu3 = new Student("2", "李四");
        hs.add(stu1);
        hs.add(stu2);
        hs.add(stu3);
        System.out.println(hs);
    }
}

  在上述代码的运行结果中,出现了两个相同的学生信息“2:李四”,这样的学生信息应该被视为重复元素,不允许同时出现在HashSet集合中。之所以没有去掉这样的重复元素,是因为在定义Student类时没有重写hashCode()和equals()方法。

  接下来对Student类进行改写,假设id相同的学生就是同一个学生,改写后代码见下。  

Java
import java.util.HashSet;
import java.util.Objects;

class Student {
    String id;
    String name;

    // 创建构造方法
    public Student(String id, String name) {
        this.id = id;
        this.name = name;
    }

    // 重写toString()方法
    @Override
    public String toString() {
        return id + ":" + name;
    }

    // 重写hashCode方法
    @Override
    public int hashCode() {
        return id.hashCode(); // 返回id属性的哈希值
    }

    // 重写equals方法
    @Override
    public boolean equals(Object o) {
        // 判断是否是同一个对象,如果是,直接返回true
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        // 判断对象是否为Student类型
        if (!(o instanceof Student)) return false;
        // 将对象强转为Student类型
        Student student = (Student) o;
        // return (id == student.id) || (id != null && id.equals(student.id));
        return Objects.equals(id, student.id);
    }
}

public class Example09 {
    public static void main(String[] args) {
        HashSet hs = new HashSet(); // 创建HashSet集合
        Student stu1 = new Student("1", "张三"); // 创建Student对象
        Student stu2 = new Student("2", "李四");
        Student stu3 = new Student("2", "李四");
        hs.add(stu1);
        hs.add(stu2);
        hs.add(stu3);
        System.out.println(hs);
    }
}

  在上述代码中,Student类重写了Object类的hashCode()和equals()方法。在hashCode()方法中返回id属性的哈希值,在equals()方法中比较对象的id属性是否相等,并返回结果。当调用HashSet集合的add()方法添加stu3对象时,发现它的哈希值与stu2对象相同,而且id.equals(student.id)返回true,HashSet集合认为两个对象相同,因此重复的Student对象被成功去除了。

  HashSet集合存储的元素是无序的,如果想让元素的存取顺序一致,可以使用Java中提供的LinkedHashSet类,LinkedHashSet类是HashSet的子类,与LinkedList一样,它也使用双向链表来维护内部元素的关系。

  接下来通过一个案例学习LinkedHashSet类的用法。 

Java
import java.util.Iterator;
import java.util.LinkedHashSet;

public class Example10 {
    public static void main(String[] args) {
        LinkedHashSet set = new LinkedHashSet();
        set.add("张三"); // 向该Set集合中添加字符串
        set.add("李四");
        set.add("王五");
        Iterator it = set.iterator(); // 获取Iterator对象
        while (it.hasNext()) { // 通过while循环,判断集合中是否有元素
            Object obj = it.next();
            System.out.println(obj);
        }
    }
}

  通过运行结果可以看出,元素迭代出来的顺序和存入的顺序是一致的。

分享: 更多

上一篇:foreach循环介绍

下一篇:TreeSet集合

好程序员公众号

  • · 剖析行业发展趋势
  • · 汇聚企业项目源码

好程序员开班动态

More+
  • HTML5大前端 <高端班>

    开班时间:2021-04-12(深圳)

    开班盛况

    开班时间:2021-05-17(北京)

    开班盛况
  • 大数据+人工智能 <高端班>

    开班时间:2021-03-22(杭州)

    开班盛况

    开班时间:2021-04-26(北京)

    开班盛况
  • JavaEE分布式开发 <高端班>

    开班时间:2021-05-10(北京)

    开班盛况

    开班时间:2021-02-22(北京)

    开班盛况
  • Python人工智能+数据分析 <高端班>

    开班时间:2021-07-12(北京)

    预约报名

    开班时间:2020-09-21(上海)

    开班盛况
  • 云计算开发 <高端班>

    开班时间:2021-07-12(北京)

    预约报名

    开班时间:2019-07-22(北京)

    开班盛况
IT培训IT培训
在线咨询
IT培训IT培训
试听
IT培训IT培训
入学教程
IT培训IT培训
立即报名
IT培训

Copyright 2011-2023 北京千锋互联科技有限公司 .All Right 京ICP备12003911号-5 京公网安备 11010802035720号