zoukankan      html  css  js  c++  java
  • 5 HashSet

    1、HashSet

      public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable

    实现原理,基于哈希表(HashMap) 实现。它不允许重复,可以有一个NULL元素,不保证顺序恒久不变。

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

     

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

     

    2、HashSet 的特性

      2.1 哈希表的存储结构:数组 + 链表,数组里的每个元素以链表的形式存储。

      2.2 如何将对象存储到哈希表中:先计算对象的hashCode值,再对数组的长度求余数,来决定对象要存储在数组中的位置。

    2.3 添加元素时把元素作为HashMap的key存储, HashMap的value使用一个固定的Object常量对象。

    2.4 Java集合里判断两个对象是否相同,先判断两个对象的hashCode 是相同,相同再用equals() 进行判断,equals相同则是同一个对象,不是则不是同一个对象。

    2.5 自定义对象根据实际情况需要重写hashCode() 与 equals()

    class Person {
        
        private String name;
        private Integer age;
        
        public Person(String name, Integer age) {
            super();
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
        
        public void setName(String name) {
            this.name = name;
        }
        
        public Integer getAge() {
            return age;
        }
        
        public void setAge(Integer age) {
            this.age = age;
        }
        
        @Override
        public int hashCode() {
            // 基数
            int prime = 31;
            int result = 1;
            result = prime * result + name == null? 0 : name.hashCode();
            result = prime * result + age;
            return result;
        }
        
        @Override
        public boolean equals(Object obj) {
            if(this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (!(obj instanceof Person)) {
                return false;
            }
            Person person = (Person)obj;
            if (!name.equals(person.getName())) {
                return false;
            } else if(age != person.getAge()) {
                return false;
            }
            return true;
        }
    
        @Override
        public String toString() {
            return "Person [name=" + name + ", age=" + age + "]";
        }
        
    }

    3、选择31作为基数的原因:

    3.1 选择系数的时候要选择尽量长的系数并且让乘法尽量不要溢出的系数,因为如果计算出来的hash地址越大,所谓的“冲突”就越少,查找起来效率也会提高。

    3.2 31*N可以被编译器优化为左移5位后减1即31*N = (N<<5)-1,有较高的性能。

     

  • 相关阅读:
    pmtk3
    SIFT算法研究
    Kd-Tree算法原理和开源实现代码
    统计学习精要
    svm
    UIUC同学Jia-Bin Huang收集的计算机视觉代码合集
    图像识别领域的一些code
    传输媒体、表示媒体、感觉媒体、表现媒体的区别
    海明码奇偶校验
    ip和子网掩码的判断
  • 原文地址:https://www.cnblogs.com/Latiny/p/10708217.html
Copyright © 2011-2022 走看看