首页 > 其他分享 >HashSet无序不重复 (去重的原因)

HashSet无序不重复 (去重的原因)

时间:2022-12-28 15:12:44浏览次数:32  
标签:System java22 HashSet 重复 无序 hashCode add println

set -> hashset treeset
set集合最最重要的一个特征就是, 自动去重 -- hashCode方法与equals方法 treeset中弥补了hashset无序的缺点, 但是代价是消耗的性能比hashset高, 比hashset执行更慢一些 HashSet 核心特性
特点1: HashSet当中存储的数据是无序的.
特点2: HashSet中存储的数据是不重复的. (重点)
重复指的是, 两个对象调用equals返还true, 并且两个对象的hashCode方法返还的结果相等
重复的意思, 指的是两个数据完全相等   HashSet方法和TreeSet方法基本相同 HashSet(散列存放的子类)
* 1.无序: 跟放入顺序无关,结果也是无序的
* 2.元素不允许重复
*
*
* 跟TreeSet不同 放入元素 尽管没有实现比较器 也不会报错 但是没有实现查重规则
* 所以HashSet的查重规则(因为没有大小比较)不是比较器
* 那么HashSet的查重规则到底是什么呢?
*
* 先调用hashCode方法 再调用equals方法进行比较
*
*
*
*HashSet集合再放入引用数据类型是 需要进行查重比较 查重的规则是先
*调用hashCode方法 如果hashCode方法相等 则再去调用equals方法 进行各项属性的比较
* 如果hashCode方法不相等 则判定两个对象不相等
*
*第一步:
*hashCode:
* 什么是hashCode方法:在Object类中定义的,默认的功能是返回当前对象跟地址值相关的一串数据(无意义)
* 那么需要我们自己覆写,覆写要实现什么样子有意义的功能呢?
* 为什么HashSet集合在放入对象时 要先比较hashCode方法 再去比较equals方法呢?直接调用equals去比较对象是否相等不就好了么?
* equals方法是对象和对象之间进行各项属性的比较 从而判断两个对象是否相等,所以效率非常低下
*
* 所以要先调用hashCode方法 进行非常效率的比较,也就是先快速比较出两个对象是否相等,
* 一旦hashCode方法比较出两个对象不相等了,那就不用去调用equals方法了 提高了效率
* 如果hashCode无法判断出这两个对象是否相等 那么就要请出我们的大哥equals方法 进行各项属性的比较了
*
*
*hashCode方法到底是什么代码?应该实现什么功能呢?
*实现根据各项属性值 动态计算出一个哈希码
*例如: age*5+name.length*3
*先进行每一个对象的哈希码比较,一旦hashCode返回值 也就是哈希码不相等 那么两个对象必然不相等,那么比较出结果,
不需要再调用equals方法
*如果hashCode返回值也就是哈希码相等,并不能说明 两个对象一定相等,因为不同的数值经过同样的算法有可能算出同样结果
*所以这个时候就要用equals方法 进行各项属性的比较 看看是否每一个属性都相等
*
*
*
*
*
*第二步:
*equasl:
* 进行各项属性的详细比较
*
*
*
* 先比较hashCode方法是为了提高比较效率
* 后用equals比较 是为了提高比较的准确率
*
* 那么我们如果不覆写这两个方法 HashSet不会报错 ,但是也没有实现查重 为什么?
* 因为如果我们没覆写,那么调用是父类Object的hashCode方法,而Object的hashCode方法返回地址值
* 只要是新创建出来的对象 地址必然不相等
* 那么如果地址相等了 hashSet还会去调用equals方法,那么此时我们依然没覆写,调用的是Obejct类的
* Object类的equals是进行==比较 比较地址
*
* 所以我们必须进行两个方法的合理覆写,定义我们想要比较的规则
*
*
* TreeSet和HashSet的区别
*
* 共同点:
* 无序:跟元素的放入顺序无关
* 没有角标
* 遍历方式
*
* TreeSet:
* 结果是排序的
* 排序规则是比较器
* 不允许出现null值
*
*
*
*
* HashSet:
* 结果是无序的
* 查重规则是hashCode和equals
* 可以有null值 多个null视为重复 只能出现一个  

public class HashSetDemo {

    /**
     *  TreeSet的常用方法
     *
     *  1. 有序  和存放的代码的执行顺序无关, 和这个对象的compareTo方法有关
     *  2. 去重  和hashset一样, 是自动去重的
     * @param args
     */
    public static void main(String[] args) {
        TreeSet<String> java22 = new TreeSet<>();

//        根据ASCII码值进行排序的
        java22.add("gp");
        java22.add("ml");
        java22.add("bw");
        java22.add("ba");
        java22.add("xk");

        java22.add("xk");

//        TreeSet<Integer> java22 = new TreeSet<>();
//
//        java22.add(400);
//        java22.add(200);
//        java22.add(300);
//        java22.add(100);



        System.out.println(java22);
    }


    /**
     * 核心方法add()
     * HashSet的其他方法   hashset虽然是属于list, 但是所有的带有角标的方法全部都没有了, 因为无序
     * @param args
     */
    public static void main4(String[] args) {

//        增删改查
        HashSet<String> java22 = new HashSet<>();
        java22.add("浩远");
        java22.add("兴宇");

//        删
//        java22.remove("浩远");

//        修改
//        如果想要将浩远 -> 屠恩侠
//        java22.remove("浩远");
//        java22.add("屠恩侠");

//        查询数据 只能通过遍历的方式查询所有数据

//        1. 通过迭代器遍历
//        Iterator<String> iterator = java22.iterator();
//        while (iterator.hasNext()){
//            System.out.println(iterator.next());
//        }

//        2. 所有能够通过迭代器遍历的方式, 都可以用增强for循环替代

//        当对集合中的数据不做删除或者新增的时候, 使用增强for循环更加简洁
//        当对集合中的数据做删除或者新增的时候, 使用迭代器, 避免一遍遍历一遍修改的bug
        for (String name: java22){
            System.out.println(name);
        }

//        System.out.println(java22);


//        hashset的其他方法
//        System.out.println(java22.contains("高鹏"));

//        获取set集合存储的数据的大小
//        System.out.println(java22.size());
    }


    /**
     * HashSet存储的数据是无序的 (了解)
     *
     * 1. HashSet方法有序或者无序 和 hashCode方法极度相关
     * 2. HashSet中的对象的存储 和 hashCode值 是否是 值大的存储在后面的位置
     *
     * 2. HashSet中对象存储 和 hashCode值相关
     *  hashCode值和15做&位运算, 将得到的结果, 结果越大的存储在越后面
     *  扩展(纯了解 后面会说): 15这个数字随着HashSet中的数据的增多, 会逐步扩充两倍
     * @param args
     */
    public static void main3(String[] args) {

//        System.out.println(16 & 15);
//        System.out.println(17 & 15);
//        System.out.println(18 & 15);
//        System.out.println(11 & 15);
//        System.out.println(12 & 15);
//        System.out.println(13 & 15);
//        System.out.println(14 & 15);
//        System.out.println(15 & 15);

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

        java22.add(new Student("刘威", 100, 18));     //3
        java22.add(new Student("高鹏", 100, 17));     //2
        java22.add(new Student("欣凯", 100, 16));     //1
        java22.add(new Student("博文", 100, 15));     //8
        java22.add(new Student("屠恩侠", 100, 14));    //7
        java22.add(new Student("屠恩侠1", 100, 13));   //6
        java22.add(new Student("屠恩侠2", 100, 12));   //5
        java22.add(new Student("屠恩侠3", 100, 11));   //4

        System.out.println(java22);
    }


    /**
     * HashSet去重是如何完成的 (重要)
     * 去重的关键在于, 判断两个对象是否相同
     * 1. hashCode方法
     * 2. equals方法
     * equals方法如果不重写的话, 判断标准是地址值是否相同
     * hashCode方法如果不重写的话, 返回的int值是当前对象的地址值
     *
     * HashSet如何判定两个对象是否重复, 需要同时满足两个条件
     * 1. 两个对象的hashCode值相同
     * 2. 两个对象调用equals方法, 返还的是true
     *
     * @param args
     */
    public static void main2(String[] args) {
        HashSet<Student> java22 = new HashSet<>();

//        我们已经改写定义了重复, 没有重写equals之前, 重复指的是 地址值相同
//        现在, 指的是, 所有属性值, 姓名, 年龄, 成绩的值都相等
        Student liuWei1 = new Student("刘威", 100, 18);
        Student liuWei2 = new Student("刘威", 100, 18);

        System.out.println(liuWei1.equals(liuWei2));
        System.out.println("刘威1和2的hashcode值");
        System.out.println(liuWei1.hashCode());
        System.out.println(liuWei2.hashCode());

        java22.add(liuWei1);
        java22.add(liuWei2);

        System.out.println(java22);
    }


    /**
     * HashSet的基本方法
     * @param args
     */
    public static void main1(String[] args) {
//        HashSet<String> java22 = new HashSet<>();
//
//        java22.add("刘威");
//        java22.add("高鹏");
//        java22.add("浩远");
//        java22.add("欣凯");
//        java22.add("刘威");
//
//        System.out.println(java22);

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

        java22.add(new Student("刘威", 100, 18));
        java22.add(new Student("刘威", 100, 18));

        System.out.println(java22);
    }
}

 

标签:System,java22,HashSet,重复,无序,hashCode,add,println
From: https://www.cnblogs.com/p1121/p/17010167.html

相关文章