• set集合HashSet


    一:

    和List接口同一级的还有Set接口,Set类型的集合,元素不能重复,存储顺序和迭代顺序没有必然联系。他的元素的唯一性是由hasCode和equals决定的。

    他的子类,常用的HashSet和LinkedHashSet。

     1 package test11;
     2 
     3 import java.util.HashSet;
     4 import java.util.Iterator;
     5 import java.util.Set;
     6 
     7 public class Hash_Demo {
     8     public  static void main(String[] args){
     9         has_Test();
    10     }
    11     public static void has_Test(){
    12         Set<String>  set_str=new HashSet<>();
    13         set_str.add("i");
    14         set_str.add("j");
    15         set_str.add("k");
    16         set_str.add("k");
    17         set_str.add("m");
    18         Iterator<String> set_it=set_str.iterator();
    19         while (set_it.hasNext()){
    20             System.out.print(set_it.next());
    21         }
    22     }
    23 }

     对于我们常用的javaAPI (String、Ineteger等)的equals和hascode方法已经重写。

    HashSet集合存储数据的结构:

    首先我们了解什么是哈希表?

    哈希表底层使用的也是数组机制,数组中也存放对象,而这些对象往数组中存放时的位置比较特殊,当需要把这些对象给数组中存放的时候,那么根据这些对象的特有的数据结合相应的算法,计算出这个对象在数据中的位置,然后把这个对象存放在数组中而这样的数组叫做哈希数组,也就是哈希表。

            当向哈希表中存放元素时,需要根据元素的特有的数据结合相应的算法,这个算法其实就是Object中的hasCode方法,由于任何对象都是Object的子类,所有任何对象都有hasCode方法,算出对象的在表中的存放位置。这里需要注意,如果两个对象的hasCode方法算出的结果一样,这样叫做哈希冲突,这个时候调用对象的equals方法,比较这两个对象是不是同一个对象,如果equals方法返回true的话,就不会把第二个对象存入哈希表中。如果返回的false的时候,就会把这个值存放在hash表中。

    这也就是保证了HashSet集合的元素的唯一性,其实就是根据对象的hascode和equals方法决定的。如果我们往集合存储自定义对象的话,需要我们重写hashcode和equals方法,来适用当前对象比较方法。

     对于javaAPI上面代码。

    对于自定义类型,需要重写hascode和equals方法。

     1 package Id_Has;
     2 
     3 
     4 import java.util.HashSet;
     5 import java.util.Iterator;
     6 
     7 public class Id_Set {
     8     public static void main(String[] args){
     9         HashSet<Person_Info>  per_set=new HashSet<>();
    10         per_set.add(new Person_Info("tom",22));
    11         per_set.add(new Person_Info("tom",22));
    12         Iterator<Person_Info> per_it=per_set.iterator();
    13         while (per_it.hasNext())
    14         {
    15             System.out.print(per_it.next());
    16         }
    17     }
    18 
    19 }
    20 
    21 class Person_Info{
    22     private String name;
    23     private int  age;
    24     public  Person_Info(String name,int age){
    25         this.name=name;
    26         this.age=age;
    27     }
    28 
    29     public String getName() {
    30         return name;
    31     }
    32     public  int getAge(){
    33         return  age;
    34     }
    35     public boolean equals(Object obj){
    36         if(obj==null){
    37             return  false;
    38         }
    39         if(obj==this){
    40             return true;
    41         }
    42         if(obj instanceof Person_Info){
    43             Person_Info new_obj=(Person_Info)obj;
    44             if(new_obj.name.equals(this.name)&& new_obj.age==this.age){
    45                 return true;
    46             }
    47         }
    48         return false;
    49     }
    50     public  int hashCode(){
    51         final  int prime=31;
    52         int result=1;
    53         result=result*prime+age;
    54         result=prime * result + ((name == null) ? 0 : name.hashCode());
    55         return result;
    56    }
    57    public String toString(){
    58         return "Person_Info[" +this.name+" "+this.age + "]";
    59    }
    60 }

    我们需要对equals方法进行重写以及hashCode方法。

    equals方法:

     1     public boolean equals(Object obj){
     2         if(obj==null){
     3             return  false;
     4         }
     5         if(obj==this){
     6             return true;
     7         }
     8         if(obj instanceof Person_Info){
     9             Person_Info new_obj=(Person_Info)obj;
    10             if(new_obj.name.equals(this.name)&& new_obj.age==this.age){
    11                 return true;
    12             }
    13         }
    14         return false;
    15     }

    hashCode方法:

    1     public  int hashCode(){
    2         final  int prime=31;
    3         int result=1;
    4         result=result*prime+age;
    5         result=prime * result + ((name == null) ? 0 : name.hashCode());
    6         return result;
    7    }

    其中hashCode方法的重写,是参考JavaApi进行重写。

    字符串的hashCode的重写,其中private int hash; // Default to 0  然后用h的值乘以31在和字符对应的数值进行计算得到一个整数作为字符串的hashCode。因为字符串这种保证了hashCode唯一性。然后我们重写的时候

    其中有个值是唯一的就是name的hashCode。

    总结如下:

    hashCode相等的,不一定对象相等。

    对象相等,hashCode相等,

     HashSet的是无序的,存储和遍历,但是如果我们想要存取顺序的怎么办呢?

    HashSet的子类有个子类:LinkedHashset。

    public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable, Serializable

    他是链表和Hashset的结合。

    code:

     1 package test11;
     2 
     3 import java.util.Iterator;
     4 import java.util.LinkedHashSet;
     5 
     6 public class LinkHash_Demo {
     7     public static void main(String[] args){
     8         linkHashTest();
     9 
    10     }
    11     public  static  void linkHashTest(){
    12         LinkedHashSet<String> link=new LinkedHashSet<>();
    13         link.add("e");
    14         link.add("f");
    15         link.add("g");
    16         link.add("i");
    17         Iterator<String> linkit=link.iterator();
    18         while (linkit.hasNext()){
    19             System.out.print(linkit.next());
    20         }
    21     }
    22 }

     输出结果:

    二:ArrayList中的判断元素是否重复原理:

    非自定义类型,ArrayList在判断一个元素是否包含这个元素,使用的是contains()方法来判断,实际上使用的equals方法来进行判断,非自定义类型的数据类型equals方法都进行重写,自定义类型的数据需要自己重写的方法,

    否则判断的是对象的内存地址是否相等。有时候我们判断一个对象是否相等,是通过对象的属性进行判断而不是单单内存地址,内存地址相等一定是同一个对象,但是对象的内存地址不相等并不能说明两个对象不相等。

    最终通过equals来遍历数组判断是否有相等元素。

    三:Hashset的add方法和contians方法

    因为set集合是无序、唯一的。那set如何判断一个元素是否重复呢?

    通过hashCode 和equals方法进行判断。首先计算出要添加元素的hashcode  然后跟集合里的元素的hashcode进行判断,如果不相等,则插入元素,如果相等的话,在和集合的元素进行equals方法的比较,返回true

    则不添加元素,如果返回false的话,添加元素。

    在对自定义类型的进行set操作的时候,需要重写equals和hashCode方法的重写。

     总结:

     1     List与Set集合的区别?
     2 List:
     3                  它是一个有序的集合(元素存与取的顺序相同)
     4                  它可以存储重复的元素            
     5              Set:
     6                  它是一个无序的集合(元素存与取的顺序可能不同)
     7              它不能存储重复的元素
     8     List集合中的特有方法
     9     void add(int index, Object element) 将指定的元素,添加到该集合中的指定位置上
    10     Object get(int index)返回集合中指定位置的元素。
    11     Object remove(int index) 移除列表中指定位置的元素, 返回的是被移除的元素
    12     Object set(int index, Object element)用指定元素替换集合中指定位置的元素,返回值的更新前的元素
    13     ArrayList:
    14     底层数据结构是数组,查询快,增删慢
    15     LinkedList:
    16     底层数据结构是链表,查询慢,增删快
    17     HashSet:
    18     元素唯一,不能重复
    19     底层结构是 哈希表结构
    20     元素的存与取的顺序不能保证一致
    21     如何保证元素的唯一的?
    22         重写hashCode() 与 equals()方法
    23     LinkedHashSet:
    24     元素唯一不能重复
    25     底层结构是 哈希表结构 + 链表结构
    26     元素的存与取的顺序一致







  • 相关阅读:
    C++ error C2678: 二进制“+”: 没有找到接受“const char [22]”类型的左操作数的运算符(或没有可接受的转换)没有与这些操作数匹配的“+”运算符...
    Qt 没有byte
    C++ 解决:错误 1 error MSB8031: Building an MFC project for a non-Unicode character set is deprecated
    .NET Core-插件如何读取指定配置结点
    CodeSmith4-案例
    CodeSmith3-对象(CodeTemplate、Response、CodeTemplateInfo)
    CodeSmith2-Property(属性)
    vscode
    OPCUA suscription TimeoutError
    OPCUA 节点层级
  • 原文地址:https://www.cnblogs.com/evilliu/p/7839017.html
Copyright © 2020-2023  润新知