• java基础33 Set集合下的HashSet集合和TreeSet集合


    单例集合体系:

    ---------| collection  单例集合的根接口
    --------------| List  如果实现了list接口的集合类,具备的特点:有序,可重复       注:集合中的有序不是指自然顺序,而是指添加进去的顺序与出来的顺序是一致的
    ------------------| ArrayList  ArrayList底层维护了一个object数组的实现的。(线程不安全),特点:查询速度快,增删速度慢。有序,可重复
    ------------------| LinkedList  LinkedList底层是使用链表结构实现的,线程不安全,特点:查询速度慢,增删速度快。有序,可重复
    ------------------| Vector(了解即可)  底层也是维护一个Object数组的实现的,实现与ArrayList是一样的,但是Vector是线程安全的,操作效率低
    --------------| Set  如果实现了set接口的集合类,具备的特点:无序,不可重复     注:集合中的无序不是指自然顺序,而是指添加元素进去的顺序与元素出来的顺序是不一致的
    ------------------| HashSet  底层是用于一个哈希表支持的,线程不安全,特点:存储速度块
    ------------------| TreeSet  底层是使用红黑树(二叉树)数据结构实现的,线程不同步(即线程不安全),不能在多线程中共享,但可以使用synchroinzedMap()方法来实现同步。特点:会对元素进行排序存储(按自然顺序

    双例集合体系:

    ----------| Map  双例集合的根接口。如果是实现了Map接口的集合类,具备的特点:存储的数据都是以键值对形式存在的,键不可重复,值可以重复
    --------------| HashMap  底层是基于哈希表实现的,HashMap允许键和值为null,线程不安全,特点:存储速度块
    --------------| TreeMap  基于红黑数(二叉树)数据结构实现的,线程不同步(即线程不安全),特点:会对元素经行排序存储
    --------------| HashTable(了解即可)   线程安全


    1、HashSet 集合

        HashSet集合是Set接口(集合)的一个实现;集合中的元素:无序,且不可重复性

    1.1、HashSet 集合常用方法

        add(Object):将指定的元素添加到集合中
        remove(object):从HashSet集合中移除指定的元素
        size():返回当前集合中元素的个数
        iterator():返回此集合中的元素的迭代器
        toArray():返回一个包含此集合中所有元素的数组    相当于把集合转换成数组的形式
        contain(object):判断某元素是否在HashSet集合中(包含关系)

    其实这几个集合的常用方法几乎一样,比如 collection集合的一些常用方法

    1.2、HashSet 集合不能添加重复元素的原理

        当调用add(Object)方法添加元素的时,首先会调用Object的hashCode方法判哈希码是否已经存在,如不存在则直接插入元素;如果已存在,则再去调用Object对象的equals()方法,判断是否返回true,如果为true则说明元素已经存在,就不能再往HashSet集合中添加元素了;如为返回false,则说明元素不存在,可以继续往HashSet集合中插入元素。

    1.3、实例

    例1

     1 package com.dhb.collection;
     2 
     3 import java.util.HashSet;
     4 
     5 /**
     6  * @author DSHORE / 2018-5-21
     7  *
     8  */
     9 /* HashSet的实现原理:往HasSet添加元素的时候,会先调用hashCode方法得到元素的咍希值,然后通过元素的哈希值经过移运算,就可以算出该元素存储在咍希表的存储位置。
    10  *  1、如果算出该元素哈希码值的存储位置处还没有任何的元素,那么该元素可以直接存储到该位置上
    11  *  2、如果算出该元素哈希码值的存储位置处已经有元素了,那么就会调用该元素的equals方法与该位置的元素做一次比较,如果equals返回值是true,那么该元素与这个位置已经存在的元素就被视为重复元素,不允许再添加了;如果equals返回的是false,那么该元素还可以添加进集合里。
    12  * */
    13 class Personer{
    14     int id;
    15     String name;
    16     
    17     public Personer(int id,String name) {
    18         this.id=id;
    19         this.name=name;
    20     }
    21     @Override
    22     public String toString() {//重写toString()的作用:让返回值以字符串的形式输出;若不重写,返回值则是内存地址
    23         return "Person [id=" + id + ", name=" + name + "]";
    24     }
    25     @Override
    26     public int hashCode() {//重写hashCode()的作用:只通过id来作判断
    27         System.out.println("========HashCode========");//输出了5遍   原因:只要add()多少次,hashCode()就运行多少遍。
    28         return id;
    29     }
    30     @Override
    31     public boolean equals(Object obj) {//重写equals()的作用:用id来判断是否是同一个元素
    32         System.out.println("======这是equals方法========");//输出了一遍  原因:只需要进行判断的元素,equals()才运行。 如:只有狗娃处,才需要判断(因为只与id有关)
    33         Personer p=(Personer)obj;
    34         return this.id==p.id;
    35     }
    36 }
    37 public class Demo11 {
    38     
    39     public static void main(String[] args) {
    40         HashSet<Personer> set=new HashSet<Personer>();//<Personer>:表示泛型
    41         set.add(new Personer(110,"狗娃"));
    42         set.add(new Personer(120,"狗剩"));
    43         set.add(new Personer(119,"狗蛋"));
    44         set.add(new Personer(1000,"狗蛋"));
    45         
    46         //假设只要编号一致,就是同一个人
    47         System.out.println("添加元素成功了吗? "+set.add(new Personer(110, "狗娃")));//返回值:false   如果不重写equals()方法,那么返回值为true。原因在代码最上面
    48         System.out.println(set);//返回值:[Person [id=119, name=狗蛋], Person [id=110, name=狗娃], Person [id=10000, name=狗蛋], Person [id=120, name=狗剩]]
    49     }
    50 }

    例2

     1 package com.dhb.collection;
     2 
     3 /**
     4  * @author DSHORE / 2018-5-21
     5  *
     6  */
     7 public class Demo13 {
     8     public static void main(String[] args) {
     9         String str1="hello";
    10         String str2=new String("hello");
    11         System.out.println("两个是同一个对象?"+(str1==str2));//返回值:false
    12         System.out.println("str1的hasCode:"+str1.hashCode());//返回值:99162322
    13         System.out.println("str2的hasCode:"+str2.hashCode());//返回值:99162322
    14         /*
    15          * HashCode默认情况下表示的内存地址,String类已经重写了Object的hasCode方法
    16          * 注意:如果两个字符串的内容一致,那么返回的hashCode码也会一致
    17          * */
    18     }
    19 }

     

    2、TreeSet 集合

        TreeSet集合也是Set接口(集合)的一个实现;集合中的元素:无序,且不可重复性。 但是TreeSet集合的存储是有序的,即:存储到集合中的元素是按自然顺序存储的。

     2.1、TreeSet集合和HashSet集合的区别

    相同点:
        都是无序,且唯一不重复的Set集合。
    不同点:

        1、从底层来说:HashSet是用哈希表来存储数据,而TreeSet是用二叉平衡树来存储数据。
        2、从功能上来说:由于排序,势必要影响速度。所以,如果不需要顺序的话,建议使用HashSet,使用Hash表存储数据的HashSet在速度上更胜一筹。如果需要顺序,则TreeSet更为明智。
        3、TreeSet是一种自带排序的set集合,而HashSet没有排序的Set集合。

    2.2、TreeSet要注意的事项

        1.往TreeSet里面添加元素时候,如果元素本具备自然顺序特性,那么就按照元素的自然顺序排序存储.
        2.往TreSet里面添加元素时候,如果元素不具备自然顺序特性,那么该元素就必须要实现Comparable接口,把元素的比较规则定义在compareTo(T o)方法中
        3.如果比较元素的时候,compareTo返回的是0,那么该元素被视为重复元素,不允许添加 (注意:TreeSet与HashCode,equals没有任何关系)
        4.往TreeSet里面添加元素时候,如果元素本身不具备自然自然顺序特性,而且元素所属类也没有实现Comparable接口,那么我们必须要在创建TreeSet的时候传入一个比较器.

    2.3、自定义比较器

      自定一个比较器只需要实现接口 Comparator<T>即可,把元素与元素之间的比较规则定义在compare方法内即可

    自定义比较器的格式:
        class 类名  implements Comparator<T>{
    
        }

    2.4、实例

    例1

     1 package com.dhb.collection;
     2 
     3 import java.util.TreeSet;
     4 
     5 /**
     6  * @author DSHORE / 2018-5-25
     7  *
     8  */
     9 class Emp1 implements Comparable<Emp>{
    10     int id;
    11     String name;
    12     int salary;
    13     public Emp1(int id, String name, int salary) {
    14         super();
    15         this.id = id;
    16         this.name = name;
    17         this.salary = salary;
    18     }
    19     public Emp1() {
    20     }
    21     public int getId() {
    22         return id;
    23     }
    24     public void setId(int id) {
    25         this.id = id;
    26     }
    27     public String getName() {
    28         return name;
    29     }
    30     public void setName(String name) {
    31         this.name = name;
    32     }
    33     public int getSalary() {
    34         return salary;
    35     }
    36     public void setSalary(int salary) {
    37         this.salary = salary;
    38     }
    39     //元素与元素的比较规则
    40     @Override
    41     public int compareTo(Emp o) {
    42         return this.salary-o.salary;
    43     }
    44 }
    45 public class Demo17 {
    46     public static void main(String[] args) {
    47         TreeSet tree=new TreeSet();
    48         tree.add('b');
    49         tree.add('c');
    50         tree.add('a');
    51         tree.add('z');
    52         tree.add('1');//如果单引号去掉,则报异常:ClassCastException;因为是两种类型的数据了,没法按自然顺序排序
    53         tree.add('f');
    54         tree.add('f');
    55         
    56         System.out.println("集合的元素:"+tree);//返回值:[1, a, b, c, f, z]    按自然顺序存储
    57     }
    58 }

    例2

     1 package com.dhb.collection;
     2 
     3 import java.util.Comparator;
     4 import java.util.TreeSet;
     5 
     6 /**
     7  * @author DSHORE / 2018-5-21
     8  *
     9  */
    10 class Emp implements Comparable<Emp>{
    11     int id;
    12     String name;
    13     int salary;
    14     public Emp() {
    15     }
    16     public Emp(int id, String name, int salary) {
    17         super();
    18         this.id = id;
    19         this.name = name;
    20         this.salary = salary;
    21     }
    22     public int getId() {
    23         return id;
    24     }
    25     public void setId(int id) {
    26         this.id = id;
    27     }
    28     public String getName() {
    29         return name;
    30     }
    31     public void setName(String name) {
    32         this.name = name;
    33     }
    34     public int getSalary() {
    35         return salary;
    36     }
    37     public void setSalary(int salary) {
    38         this.salary = salary;
    39     }
    40     //元素与元素的比较规则  (根据指定字段进行比较 排序存储)
    41     @Override
    42     public int compareTo(Emp o) {
    43         //System.out.println(this.name+"compare"+o.name);
    44         return this.salary-o.salary;
    45     }
    46     /*@Override
    47     public String toString() {
    48         return "Emp [id=" + id + ", name=" + name + ", salary=" + salary + "]";
    49     }*/
    50     @Override
    51     public String toString() {
    52         return "Emp(编号=" + id + ", 名字=" + name + ", 薪资=" + salary + ")";
    53     }
    54 }
    55 //自定义比较器   作用:用于根据指定字段进行比较 排序存储
    56 class MyComparator implements Comparator<Emp>{
    57     @Override
    58     public int compare(Emp o1, Emp o2) {    
    59         return o1.salary-o2.salary;
    60     }    
    61 }
    62 public class Demo16 {
    63     public static void main(String[] args) {
    64         //调用自定义比较器
    65         /*MyComparator comparator = new MyComparator();
    66         TreeSet tree=new TreeSet(comparator);
    67         */
    68         TreeSet<Emp> tree=new TreeSet<Emp>();
    69         tree.add(new Emp(2,"张三",3000));
    70         tree.add(new Emp(3,"李四",4000));
    71         tree.add(new Emp(4,"王五",3500));
    72         tree.add(new Emp(7,"王虎",3500));
    73         tree.add(new Emp(5,"赵六",35000));
    74         tree.add(new Emp(6,"老李",4500));
    75         
    76         System.out.println("集合的元素:"+tree);//返回值:[Emp(编号=2,名字=张三,薪资=3000), Emp(编号=4,名字=王五,薪资=3500), Emp(编号=3,名字=李四,薪资=4000), Emp(编号=6,名字=老李,薪资=4500), Emp(编号=5,名字=赵六,薪资=35000)]
    77     }
    78 }

    例3

     1 package com.dhb.collection;
     2 
     3 import java.util.Iterator;
     4 import java.util.TreeSet;
     5 
     6 /**
     7  * @author DSHORE / 2018-5-21
     8  *
     9  */
    10 /*
    11  * 需求:将字符串中的数值进行排序.
    12  *         例如String str="8,1,23,2,16,98";-------->"1,2,8,16,23,98"
    13  * */
    14 public class Demo15 {
    15     public static void main(String[] args) {
    16         String str="8,1,23,2,16,98";
    17         String[] datas=str.split(",");//split():返回是一个数组
    18         
    19         TreeSet tree=new TreeSet();
    20         for (int i = 0; i < datas.length; i++) {
    21             tree.add(Integer.parseInt(datas[i]));//字符串转int类型数据是需要使用Integer.paserInt()。  paserInt():获取原始数据类型的一个特定的字符串
    22         }
    23         //遍历treeSet集合中的元素拼接成对应的字符串
    24         Iterator it=tree.iterator();
    25         while(it.hasNext()){
    26             System.out.print("["+it.next()+"]"+",");//返回值:[1],[2],[8],[16],[23],[98],
    27         }
    28     }
    29 }

    原创作者:DSHORE

    作者主页:http://www.cnblogs.com/dshore123/

    原文出自:https://www.cnblogs.com/dshore123/p/9068474.html

    欢迎转载,转载务必说明出处。(如果本文对您有帮助,可以点击一下右下角的 推荐,或评论,谢谢!

  • 相关阅读:
    PAT 1012 数字分类 (20)
    HDU 3903 Trigonometric Function(数学定理)
    HUST 1600 Lucky Numbers
    HUST 1599
    FZU 2092 收集水晶(记忆化搜索)
    Java实现 蓝桥杯 算法训练 字符串长度(IO无敌)
    Java实现 蓝桥杯 算法训练 字符串长度(IO无敌)
    Java实现 蓝桥杯 算法训练 Remember the A La Mode(暴力)
    Java实现 蓝桥杯 算法训练 Remember the A La Mode(暴力)
    Java实现 蓝桥杯 算法训练 Remember the A La Mode(暴力)
  • 原文地址:https://www.cnblogs.com/dshore123/p/9068474.html
Copyright © 2020-2023  润新知