• java笔记之set集合hashset和treeset<四>


    ---| Set接口     无序,不可以重复的集合  

                                ---| HashSet  线程不安全,存取速度快。底层是以hash表实现的。

                                ---| TreeSet  红-黑树的数据结构,默认对元素进行自然排序(String)。如果在比较的时候两个对象返回值为0,那么元素重复。

    1.HashSet

    哈希表边存放的是哈希值。HashSet存储元素的顺序并不是按照存入时的顺序(和List显然不同) 是按照哈希值来存的所以取数据也是按照哈希值取得。

    HashSet不存入重复元素的规则.使用hashcodeequals

    HashSet到底是如何判断两个元素重复。

    通过hashCode方法和equals方法来保证元素的唯一性,add()返回的是boolean类型

    判断两个元素是否相同,先要判断元素的hashCode值是否一致,只有在该值一致的情况下,才会判断equals方法如果存储在HashSet中的两个对象hashCode方法的值相同equals方法返回的结果是true,那么HashSet认为这两个元素是相同元素只存储一个(重复元素无法存入)。

    注意:HashSet集合在判断元素是否相同先判断hashCode方法,如果相同才会判断equals。如果不相同,是不会调用equals方法的。

    哈希值相同equalsfalse的元素是怎么存储呢,就是在同样的哈希值下顺延(可以认为哈希值相同的元素放在一个哈希桶中)。也就是哈希一样的存一列。

    1hashCode值不相同的情况

    2hashCode值相同,但equals不相同的情况。

    import java.util.HashSet;
    class Emp{
        int id;
        String name;
        int salary;
        public Emp(int id,String name,int salary){
            this.id=id;
            this.name=name;
            this.salary=salary;
        }
        @Override
        public String toString() {
            return "  (编号  "+this.id+" 姓名  "+this.name+" 薪水 "+this.salary+" )  ";
        } 
        @Override
        public int hashCode() {//重写hashcode方法
            return this.id;
        }
        @Override
        public boolean equals(Object obj) {//重写equal方法,判断id和name一致时为true
            if (obj instanceof Emp) {
                Emp emp =(Emp) obj;
                return this.id==id&&this.name.equals(emp.name);
            } else {
                    return false;
            }
        }
    }
    
    public class hashset02 {
        public static void main(String[] args) {
            HashSet set =new HashSet();
            set.add(new Emp(110, "allen",1000));
            set.add(new Emp(110, "leeleo",1000));
            set.add(new Emp(110, "allen",1000));
            System.out.println("重写方法后输出:"+set);
        }
    }

    重写方法后输出:[  (编号  110 姓名  allen 薪水 1000 )  ,   (编号  110 姓名  leeleo 薪水 1000 )  ]

    此处的set.add(new Emp(110, "allen",1000));和第一次加入对象的hashcode和equal比较后,都返回true。所以就无法存储。把equal方法屏蔽后输出:

    [  (编号  110 姓名  allen 薪水 1000 )  ,   (编号  110 姓名  leeleo 薪水 1000 )  ,   (编号  110 姓名  allen 薪水 1000 )  ]

    是由于第一次和第三次的hashcode虽然一致,但equal方法未重新,比较的是内存地址,返回的是false。所以可以存储。存储的方式如图二所示。

    2.TreeSet

    -黑树

    红黑树是一种特定类型的二叉树。红黑树算法的规则: 左小右大。既然TreeSet可以自然排序,那么TreeSet必定是有排序规则的。

    1:让存入的元素自定义比较规则。

    如果元素具备自然顺序的特性,那么就按照元素自然顺序的特性进行排序存储。

    import java.util.TreeSet;
    
    public class Demo01 {
            public static void main(String[] args) {
                TreeSet set =new TreeSet ();
                set.add(4);
                set.add(2);
                set.add(9);
                set.add(5);
                set.add(8);
                set.add(1);
                System.out.println(set);        
            }
    }

    输出结果:[1, 2, 4, 5, 8, 9]

    2.treeSet添加自定义元素:

    treeSet要注意的事项:
    1. 往TreeSet添加元素的时候,如果元素本身具备了自然顺序的特性,那么就按照元素自然顺序的特性进行排序存储。
    2. 往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,那么该元素所属的类必须要实现Comparable接口,把元素的比较规则定义在compareTo(T o)方法上。 
    3. 如果比较元素的时候,compareTo方法返回 的是0,那么该元素就被视为重复元素,不允许添加.(注意:TreeSet与HashCode、equals方法是没有任何关系。)
    4. 往TreeSet添加元素的时候, 如果元素本身没有具备自然顺序 的特性,而元素所属的类也没有实现Comparable接口,那么必须要在创建TreeSet的时候传入一个比较器。
    5. 往TreeSet添加元素的时候,如果元素本身不具备自然顺序的特性,而元素所属的类已经实现了Comparable接口, 在创建TreeSet对象的时候也传入了比较器那么是以比较器的比较规则优先使用。


    如何自定义定义比较器: 自定义一个类实现Comparator接口即可,把元素与元素之间的比较规则定义在compare方法内即可


    自定义比较器的格式 :

    class 类名 implements Comparator{

    }
    推荐使用:使用比较器(Comparator)。 

     

  • 相关阅读:
    iOS- Swift:使用FMDB进行数据库操作(线程安全:增删改查)
    iOS- Swift:如何使用iOS8中的UIAlertController
    iOS- Swift和Object-C的混合编程
    iOS- 再谈ARC里内存问题,ARC里数组、对象内存得不到释放?
    iOS- 如何建立索引实现本地文本搜索引擎,允许容错搜索?
    iOS- 全方位解析.crash文件崩溃报告
    iOS- 关于AVAudioSession的使用——后台播放音乐
    iOS- Autolayout自动布局
    iOS- 详解如何使用ZBarSDK集成扫描二维码/条形码,点我!
    419. Roman to Integer【medium】
  • 原文地址:https://www.cnblogs.com/AllenRandolph/p/6952218.html
Copyright © 2020-2023  润新知