博客> Java Collection类的学习---Set
Java Collection类的学习---Set
2017-12-13 12:22 评论:0 阅读:192 西单_夜未央
set JAVA 重写hashCode equals HashSet

悠然的午后时分,喜欢泡在星巴克,坐着疲软的凳子,蹭着免费的wifi,伴随着一缕缕coffee 的醇香,仍书页划过指尖。

今天主要学习的集合collection的另一个子类---Set:

查看IPA 感觉没什么新的方法,但是有一个与List很明显的特点:无序(底层的排序应该是有的),唯一

首先的一个Demo,当然是我们的String对象,感觉都验证,于是实验自定义的对象Student,

public static void main(String[] args) {

  HashSet<Student> hs = new HashSet<Student>();

  Student s1 = new Student("周星驰", 65);
  Student s2 = new Student("林黛玉", 17);
  Student s3 = new Student("刘德华", 65);
  Student s4 = new Student("周星驰", 65);
  Student s5 = new Student("周星驰", 63);

  hs.add(s1);
  hs.add(s2);
  hs.add(s3);
  hs.add(s4);
  hs.add(s5);

  Iterator<Student> it = hs.iterator();
  while(it.hasNext()){
   Student s = it.next();
   System.out.println(s);
  }
 }

**但是没有达到预期的效果:没有去重 于是我又去检查:A:对象的equals方法我重写了啊! B:逻辑也没错啊! 天啊,我要奔溃,于是看是苦逼的查看方法底层的实现

    class HashSet<E>
{
 private HashMap map;
 private static final Object PRESENT = new Object();

 public HashSet()
 {
  map = new HashMap();
 }

 public boolean add(E e) {  //e = s1;
        return map.put(e, PRESENT)==null;
    }
}

class HashMap
{
 //key = s1,
 //value = obj;
 public V put(K key, V value) {
        if (table == EMPTY_TABLE) {
            inflateTable(threshold);
        }
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key); //根据s1对象hashCode()方法计算
        int i = indexFor(hash, table.length);
        for (Entry<K> e = table[i]; e != null; e = e.next) {
            Object k;
     //hashcode不一样
  举例:   
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

    //k = s1
    final int hash(Object k) {
        int h = hashSeed;
        if (0 != h && k instanceof String) {
            return sun.misc.Hashing.stringHash32((String) k);
        }

        h ^= k.hashCode();

        // This function ensures that hashCodes that differ only by
        // constant multiples at each bit position have a bounded
        // number of collisions (approximately 8 at default load factor).
        h ^= (h >>> 20) ^ (h >>> 12);
        return h ^ (h >>> 7) ^ (h >>> 4);
    }
}

HashSet hs = new HashSet();

Student s1 = new Student("周星驰",65);

hs.add(s1);
  • if(e.hash == hash && ((k = e.key) == key || key.equals(k)))
  • {
  • 唯一。
  • }
  • 分析条件:
  • A:这个判断跟对象的hashCode()方法相关。
  • B:这个判断跟equals()方法相关。
  • 很明显,这是一个与条件,必须先满足前面的hash条件
  • 看了hash方法,貌似看不懂,使一些位运算
  • 查了一下资料,说可以重写hashcode的方法,像重写equal方法:

         * hashCode():把所有成员变量值相加。如果是引用类型,用哈希值。如果是基本类型直接用值。
         *  Person:
         *  String name;
         *  int age;
         *  char sex;
         *  float score;
         * 
         *  public int hashCode()
         * {
         * return this.name.hashCode()+this.age*13+this.sex*17+this.score*21;
         * }
         * equals():三步。
         * A:this == obj
         *  B:!(obj instanceof Student)
         *  C:this.name.equals(s.name) && this.age == s.age && this.sex == s.sex && this.score == s.socre;

但是,但是,我也是醉了,eclipse 右键源码里就有自动重写hash Code 和equals的方法,好吧,真是一次不错的阅读源码的机会

收藏
1
sina weixin mail 回到顶部