解决方案 »

  1.   

    HashSet在你调用add的时候,就会调用添加的对象的hashCode方法,而equals方法是在你某些操作的时候,比如remove,HashSet来判断到底是哪一个对象所调用的方法
      

  2.   


        private transient HashMap<E,Object> map;    // Dummy value to associate with an Object in the backing Map
        private static final Object PRESENT = new Object();    public boolean add(E e) {
    return map.put(e, PRESENT)==null;
        }这是 hashset 代码中的一部分,hashset 底层是用hashmap来存储的,hashset 存储的值  存放到map中的key,value值 就是PRESENT(一个模拟值而已)。这你就该明白了吧,hashMap的 key 是不能,也不会重复的,hashmap的源码是怎么实现 key不能重复的机制,就是 set集合不能重复的实现。
      

  3.   

    简单点给你说,add的时候调用equals,在你查找的时候调用hashcode,所以hashcode写得好坏会影响查找效率。
      

  4.   

    下面是我自己的代码练习和理解,不知道是不是你需要的
    ===================================================================================
    package com.test.example;import java.util.HashSet;class Student /*extends Object*/{ //Object是所有自定义类的父类
    //hashCode和equals方法是Object中已定义的方法,所有类都有这两个方法
    int Sno;
    String Sname = null;
    public Student(int Sno, String Sname){
    this.Sno = Sno;
    this.Sname = Sname;
    }
    //hashCode先被调用,如果在集合中有与当前元素一致的hashCode,调用equals进一步比对
    //1.需要重写一个方法hashCode(哈希码)
    public int hashCode(){
    System.out.println("生成hashCode"); //添加元素时自动调用hashCode
    return Sno;
    }
    //2.重写equals方法
    public boolean equals(Object obj){
    Student s = (Student)obj;
    System.out.println("equals被调用 [" + Sname + "] -- [" + s.Sname + "] ");
    boolean b = Sno == s.Sno;
    //boolean b = Sname.equals(s.Sname);
    return b; //返回true表示一致
    }


    }
    public class StudentSet {
    public static void main(String[] args){
    /**当使用HashSet存储自定义类时,需要在自定义类中重写equals和hashCode方法,
     * 主要原因是集合内不允许有重复的数据元素,在集合校验元素的有效性时(数据元素不可重复),
     * 需要调用equals和hashCode验证。
     * */
    HashSet<Student> stuSet = new HashSet<Student>();
    Student s1 = new Student(1, "Lily");
    Student s2 = new Student(2, "Tom");
    Student s3 = new Student(3, "Jay");
    Student s4 = new Student(3, "Jay");
    /*stuSet.add(s1);
    stuSet.add(s2);
    stuSet.add(s3);
    stuSet.add(s4);
    //System.out.println(stuSet);
    //因为没有重写toString方法,所以返回Object默认toString,显示的是元素的位置
    System.out.println("stuSet的大小是:" + stuSet.size());//重写之前,stuSet的大小是:4
    //s3和s4一样,但是stuSet将其视作两个元素
    //因为Student是自定义类,Set不能判断自定义类什么时候重复,所以需要重写hashCode方法和equals方法
    */
    System.out.println("-------------------0-------------------");
    stuSet.add(s1);
    System.out.println("-------------------1-------------------");
    stuSet.add(s2);
    System.out.println("-------------------2-------------------");
    stuSet.add(s3);
    System.out.println("-------------------3-------------------");
    stuSet.add(s4);
    System.out.println("-------------------4-------------------");
    System.out.println("stuSet的大小是:" + stuSet.size());
    /*结果显示:
                            -------------------0-------------------
    生成hashCode
    -------------------1-------------------
    生成hashCode
    -------------------2-------------------
    生成hashCode
    -------------------3-------------------
    生成hashCode
    equals被调用 [Jay] -- [Jay] 
    -------------------4-------------------
    stuSet的大小是:3
     * */
    //当将自定义类的对象存储到set中时,会先自动调用hashCode,如果不一致,直接添加元素(不调用equals方法)
    //当hashCode一致时,再调用equals进行比较,如果不一致添加元素,如果一致则舍弃
    }
    }
      

  5.   

    不知道API介绍的方法底层大致什么逻辑,就看源码吧!