• Java 编程下 HashSet 存入相同元素的原理


    package cn.sunzn.memoryleak;
    
    import java.util.Collection;
    import java.util.Collections;
    import java.util.HashSet;
    /**
    * HashSet 的底层是由 HashMap 实现的,HashSet 存储的值会被当作 HashMap 中的 Key 来存储同时
    * 这个 Key 会和一个固定的充当 Value 的值共同组成一个 Entry,这个 Entry 会调用 hashCode()方法
    * 计算出一个 hashCode 值作为这个 Entry 的属性。当存入下一个值的时候 HashSet 内部会计算当前存
    * 入的值和固定的 Value 值组成的 Entry 的 hashCode 值并和上一个存入值的 hashCode 属性进行比
    * 对,如果不同,则存入;如果相同则不存入。如果这时将存入值的 Key 进行修改,然而对应的hashCode
    * 属性值却不会因为 Key 值的改变而重新计算,而是会保留开始存入时计算好的 hashCode 值。这时再存
    * 入和被修改后相同的 HashSet 值进去的时候,程序会对这个新存入的 HashSet 值和固定的 Value 值
    * 组成的 Entry 计算出新的 hashCode 值进和上一个修改后的 Entry 进行比对,然而,上一个存入的值
    * 保存了未修改前的 hashCode 值,这时就会出现有相同的值存入 HashSet 的情况。但是这时如果要存入
    * 和第二个值修改前相同的值,就会出现不能存入的现象,因为它们会计算出相同的 hashCode 值。
    */
    public class ReflectTest {
    
       public static void main(String[] args) {
           Collection<ReflectPoint> collection = new HashSet<ReflectPoint>();
    
           ReflectPoint point1 = new ReflectPoint(3, 3);
           ReflectPoint point2 = new ReflectPoint(3, 5);
           ReflectPoint point3 = new ReflectPoint(3, 3);
           ReflectPoint point4 = new ReflectPoint(3, 7);
    
           Collections.addAll(collection, point1, point2, point3);
    
           System.out.println("HashSet 的长度:" + collection.size());
    
           point1.setY(7);
    
           System.out.println("HashSet 的长度:" + collection.size());
    
           collection.add(point4);
    
           System.out.println("HashSet 的长度:" + collection.size());
           System.out.println("point1 的 hashCode 值:" + point1.hashCode());
           System.out.println("point4 的 hashCode 值:" + point4.hashCode());
           System.out.println("point1 和 point4 的 equals 比较:" + point1.equals(point4));
           System.out.println("point1 和 point4 的内存地址比较:" + (point1 == point4));
           System.out.println(collection);
           
           collection.add(point1);
           System.out.println("HashSet 的长度:" + collection.size());
       }
    
    }
    运行结果:
    HashSet 的长度:2
    HashSet 的长度:2
    HashSet 的长度:3
    point1 的 hashCode 值:1061
    point4 的 hashCode 值:1061
    point1 和 point4 的 equals 比较:true
    point1 和 point4 的内存地址比较:false
    [ReflectPoint [x=3, y=5], ReflectPoint [x=3, y=7], ReflectPoint [x=3, y=7]]
    HashSet 的长度:3

    下面的代码为上面 ReflectTest 类用到的 ReflectPoint 类:

    package cn.sunzn.memoryleak;
    
    public class ReflectPoint {
       private int x;
       private int y;
       
       public ReflectPoint(int x, int y) {
           super();
           this.x = x;
           this.y = y;
       }
    
       public int getX() {
           return x;
       }
    
       public void setX(int x) {
           this.x = x;
       }
    
       public int getY() {
           return y;
       }
    
       public void setY(int y) {
           this.y = y;
       }
    
       public int hashCode() {
           final int prime = 31;
           int result = 1;
           result = prime * result + x;
           result = prime * result + y;
           return result;
       }
    
       public boolean equals(Object obj) {
           if (this == obj)
               return true;
           if (obj == null)
               return false;
           if (getClass() != obj.getClass())
               return false;
           ReflectPoint other = (ReflectPoint) obj;
           if (x != other.x)
               return false;
           if (y != other.y)
               return false;
           return true;
       }
    
       public String toString() {
           return "ReflectPoint [x=" + x + ", y=" + y + "]";
       }
    }
  • 相关阅读:
    ssm整合用到的依赖jar包(不充足)
    eclipse中Maven web项目的目录结构浅析
    何时使用抽象类?何时使用接口?
    $().attr() 和 $().css的区别
    AJAX防重复提交的办法总结
    CentOS 8 扩展LVM,更改xfs卷报错解决方法
    安装Minikube无法访问k8s.gcr.io的简单解决办法
    Windows 10、Ubuntu 18.04 双系统 双硬盘 安装经验总结
    转眼十年
    Dresdon二次开发
  • 原文地址:https://www.cnblogs.com/sunzn/p/2910910.html
Copyright © 2020-2023  润新知