• Java学习笔记31(集合框架五:set接口、哈希表的介绍)


    set接口的特点:

    1.不包含重复元素

    2.set集合没有索引,只能用迭代器或增强for循环遍历

    3.set的底层是map集合

    方法和Collection的方法基本一样

    set接口的实现类HashSet:

    1.无序集合

    2.可以存入空(null)

    3.不可以存在重复元素

    示例:

    package demo;
    
    import java.util.HashSet;
    import java.util.Iterator;
    import java.util.Set;
    
    public class HashSetDemo {
        public static void main(String[] args) {
            Set<String> set = new HashSet<String>();
            set.add("abc1");
            set.add("abc1");
            set.add("abc2");
            set.add("abc3");
            set.add("abc4");
            Iterator<String> i1 = set.iterator();
            while(i1.hasNext()){
                System.out.println(i1.next());
            }
        }
    }
    /*
    输出:
    注意:这里的输出特点是无序的
    abc1
    abc4
    abc2
    abc3
    */

    set底层数据结构是哈希表:

    特点:存储取出都比较快

    原理:具体省略,简单说就是链表数组结合体

    对象的哈希值:普通的一个整数

    可以理解为身份证号,是hashset存储的依据

    package demo;
    
    public class Person {}
    package demo;
    
    public class HashDemo {
        public static void main(String[] args) {
            Person p = new Person();
            int i = p.hashCode();
            System.out.println(i);
            //每次运行都会输出不同的整数,比如1191201656
            
            String s1 = new String("abc");
            String s2 = new String("abc");
            System.out.println(s1.hashCode());//96354
            System.out.println(s2.hashCode());//96354
            //这里Stirng重写hashcode方法,有对应的计算公式
            //当字符串的内容相同时候,运算结果就相同,因此s1和s2的哈希值相同
        }
    }

    哈希表存储过程:


    1.调用对象的哈希值

    2.集合在容器内搜索有没有重复的哈希值,如果没有,存入新元素,记录哈希值

    3.再次存储,重复上边的过程

    4.如果有重复的哈希值,调用后来者的equals方法,参数为前来者,结果得到true,集合判断为重复元素,不存入

    相同的字符串如果存进去,哈希值相同,equals方法为true,不会存入相同的

    只要哈希值相同或者equals方法为true都成立才不会存入,只要其中一条不满足,都会储存

    哈希表存储自定义对象:

    package demo;
    
    public class Person {
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String toString() {
            return this.name + ":" + this.age;
        }
    
        public Person() {
        }
    
        public Person(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
    
    }
    package demo;
    
    import java.util.HashSet;
    
    public class HashDemo {
        public static void main(String[] args) {
            HashSet<Person> setPerson = new HashSet<Person>();
            setPerson.add(new Person("a",17));
            setPerson.add(new Person("b",20));
            setPerson.add(new Person("b",20));
            setPerson.add(new Person("c",18));
            System.out.println(setPerson);
            //[c:18, b:20, a:17, b:20]
            //发现存入了重复的元素
            //所以想办法使name和age相同的Person对象视为同一个对象
            //所以需要重写hashcode方法
        }
    }

    自己重写:

    package demo;
    
    public class Person {
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String toString() {
            return this.name + ":" + this.age;
        }
    
        public Person() {
        }
    
        public Person(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
        public int hashCode(){
            return name.hashCode()+age*66;
        }
    
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (obj instanceof Person) {
                Person p = (Person) obj;
                return name.equals(p.name) && age == p.age;
            }
            return false;
        }
    }

    eclipse可以帮助我们写:

    package demo;
    
    public class Person {
        private String name;
        private int age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String toString() {
            return this.name + ":" + this.age;
        }
    
        public Person() {
        }
    
        public Person(String name, int age) {
            super();
            this.name = name;
            this.age = age;
        }
    
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + age;
            result = prime * result + ((name == null) ? 0 : name.hashCode());
            return result;
        }
    
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Person other = (Person) obj;
            if (age != other.age)
                return false;
            if (name == null) {
                if (other.name != null)
                    return false;
            } else if (!name.equals(other.name))
                return false;
            return true;
        }
    
    }

    LinkedHashSet集合:基于链表的哈希表实现,继承HashSet,它具有顺序

    示例:

    package demo;
    
    import java.util.LinkedHashSet;
    
    public class LinkedHashSetDemo {
        public static void main(String[] args) {
            //有序的set
            LinkedHashSet<Integer> link = new LinkedHashSet<Integer>(); 
            link.add(1);
            link.add(2);
            link.add(3);
            link.add(4);
            System.out.println(link);
            //[1, 2, 3, 4]
        }
    }

    关于hashcode和equals的一些问题,在面试中会问道:

    1.两个对象哈希值相同,那么equals方法一定返回true吗?不一定

    取决于如何重写equals,如果重写固定了它返回false,结果就一定是false

    2.equals方法返回true,那么哈希值一定相同吗?一定

    如果类中定义一个静态变量(static int a = 1),然后重写hashcode返回a+1,那么每一个对象的哈希值都不一样

    不过java中规定:对象相等,必须具有相同的哈希码值,所以这里是一定的

  • 相关阅读:
    configure错误列表供参考
    php和AJAX用户注册演示程序
    php中文汉字截取函数
    阻止a标签点击跳转刷新
    js日期插件
    apache 开启Gzip网页压缩
    查询文章的上下篇Sql语句
    thinkphp简洁、美观、靠谱的分页类
    thinkphp自定义模板标签(二)
    thinkphp自定义模板标签(一)
  • 原文地址:https://www.cnblogs.com/xuyiqing/p/8278527.html
Copyright © 2020-2023  润新知