首页 > 编程语言 >java修改Set中的元素

java修改Set中的元素

时间:2023-06-14 15:22:26浏览次数:44  
标签:set java s1 元素 hashCode Stu Set id

java修改Set中的元素

一.问题的提出

在java中,有以下代码:

public class Test{
    public static void main(String[] args) {
        Set<Stu> set = new HashSet<>();
        Stu s1 = new Stu(1);
        Stu s2 = new Stu(2);
        set.add(s1);
        set.add(s2);
        s1.id = 2;

        System.out.println(set.size());
        System.out.println(s1.equals(s2));
        System.out.println(s1.hashCode() == s2.hashCode());
    }
}

class Stu{
    public int id;
    public Stu(int id){
        this.id = id;
    }

    @Override
    public boolean equals(Object s){
        if(s instanceof Stu){
            Stu temp = (Stu) s;
            if(temp.id == this.id){
                return true;
            }

        return false;
        }
        
        return false;
    }
    
    @Override
    public int hashCode(){
        return Objects.hash(id);
    }

}

运行该代码,会发现输出

2
true
true

意思是在Set中出现两个相同的元素(equals比较时相同,hashCode也相同),这不符合Set中无重复元素的定义。为此,我来分析一下这个问题。

二.问题的分析

调试该程序,我们得到如下结果。

img

可以看到,s1和s2虽然hashCode相同,equals方法也会返回true,但还是存在两个不同的地址中,只是通过修改equals和hashCode方法,让它们在逻辑上相同了。这时,如果我们再重新建立一下set,如下所示:

public static void main(String[] args) {
    Set<Stu> set = new HashSet<>();
    Stu s1 = new Stu(1);
    Stu s2 = new Stu(2);
    set.add(s1);
    set.add(s2);
    s1.id = 2;

    System.out.println(set.size());
    System.out.println(s1.equals(s2));
    System.out.println(s1.hashCode() == s2.hashCode());

    set = set.stream().collect(Collectors.toSet());
    System.out.println(set.size());
}

这时,我们发现set的大小又变成了1。

三.问题结论

通过上面的小实验,我们可以看到,java是在Set建立和往其中加元素时保证的Set的中元素不重复,但如果元素已经放入集合中,再通过指针修改其中的元素,Set是无法保证其中元素被修改后仍然不重复的。

为了维护Set集合中的元素不重复的特性,我们可以遵循以下原则:

  1. 避免更改已经加入 Set 集合中的对象的属性值。如果需要更改对象的属性值,可以先从集合中删除该对象,然后更改属性值后再将其重新添加到集合中。
  2. 在定义用于比较对象是否相等的 equalshashCode 方法时,可以考虑使用不可变的属性作为比较依据。这样,即使对象的其他属性发生了变化,也不会影响到对象在 Set 集合中的唯一性。
  3. 如果需要在 Set 集合中存储可变对象,并且需要频繁更改对象的属性值,可以考虑使用其他数据结构,例如 ListMap,来替代 Set 集合。

标签:set,java,s1,元素,hashCode,Stu,Set,id
From: https://www.cnblogs.com/tryingWorm/p/17480303.html

相关文章

  • Java集合去重的几种方法
    一、List的contains方法去重示例代码如下:importjava.util.ArrayList;importjava.util.List;/***@authorqinxun*@date2023-06-13*@Descripion:List集合去重*/publicclassRepeatDemo{publicstaticvoidmain(String[]args){longstart=S......
  • java面试算法:设计搜索输入框的输入提示功能
    我们使用搜索引擎时,需要在搜索框输入关键字,当你在框中输入头几个字符时,搜索框会出现一个下拉框,里面包含着以当前输入字符为前缀的字符串,如果里面包含你想要输入的内容,那么你就可以直接选取,而不必要把关键字的所有字符依次输入,这种功能极大的提高了搜索体验。本次算法题的题目是,你如......
  • HTML页面元素解释
    HTML代表超文本标记语言,是用于在万维网上创建网页和构建其内容的标准标记语言。HTML是Web开发的支柱,也是创建基于Web的文档的基本构建块。让我们快速看一下它是如何工作的。(更多优质内容:java567.com)HTML有什么作用?HTML的主要作用是通过使用一组标签或元素来定义网页的......
  • JavaScript 动态编辑元素某属性值(例如:元素div的class属性)
    元素<divclass="h5-box-search-itemusimglistnodisplay"id="usimglist"></div>(满足条件)动态更新div元素的class属性值://获取目标容器letusimglist=document.getElementById('usimglist');//获取其class的属性值letclassinfo=usimglist.ge......
  • 从n个不同元素中有放回的取出r个且不计顺序,有多少种不同的取法?
    从n个不同元素中有放回的取出r个且不计顺序,有多少种不同的取法?答案是:\(C_{n+r-1}^r\)解析因为是有放回地取出,所以同一个元素可能会被取多次,并且取出的元素是不计顺序的,那么如果我们设\(x_i\)为第\(i\)个元素被取出的次数,问题就被转化为:\[\begin{aligned}x_1+x_2+\cdots+x_n......
  • Java8-Consumer的使用场景
    Java8的Consumer比较抽象。结合几个例子来看看常用的使用场景有以下几个:把方法作为函数的入参Java8中可以使用Consumer来实现在函数的入参中传递方法,这个如果熟悉js的话可能会比较好理解一些。在某些情况下,不能直接使用某个对象的方法,需要把方法传递到另一个函数里面去执行,那么......
  • Java8-Predicate 策略模式的替代品消灭 if else
    使用策略模式消灭ifelse,可以利用Java8的新特性来实现策略模式。利用Java8的Predicate消灭ifelse。首先定义一个map,key是不同的服务代码,value是需要做校验的条件,然后针对不同的服务代码做校验。当然Supplier、Consumer都可以做类似的实现。//定义校验的策略映射关系staticM......
  • Java8-并行流的使用
    Java8中的并行流使用publicclassStreamTest{publicList<Person>constructPersons(){List<Person>persons=newArrayList<Person>();for(inti=0;i<5;i++){Personp=newPerson(i,"name"+......
  • JavaScript中数组(Array)与对象(Object)中的检索方式
    这里只是要说明一点,数组(Array)和对象(Object)都可以用[...]的方式来进行检索[...]中包含的需要是一个表达式,这个表达式的值最终会以字符串的形式被使用因为不论是数组(Array)还是对象(Object),他们都是以键值对的形式存储内容的,而所有的键的数据类型都是字符串(Array好像不是,但是先这样......
  • 编译原理动手实操,用java实现编译器-算术表达式及其语法解析器的实现
     本节代码下载地址:http://pan.baidu.com/s/1sjWiwPn代码的理解和运行是吃透编译原理的关键,如果我们看的是爱情动作片,自然选择无码的好,但如果看得是计算机课程,则必须有码,无码的计算机理论都是耍流氓。当前,java所实现的简易编译器目的是将一条或一组含有加号和乘号的算术表达式编译......