• Java 之 HashSet 集合


    一、概述

      java.util.HashSet  是 Set 接口的一个实现类,它所存储的元素是不可重复的,并且元素都是无序的(即存取顺序不一致)。

      java.util.HashSet 底层的实现是一个 java.util.HashMap 支持。

      HashSet 是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存储区和查找性能。保证元素唯一性的方式依赖于:hashCode 与 equals 方法。

      特点

        1. 不允许存储重复的元素

        2. 没有索引,也没有带索引的方法,不能使用普通 for 循环遍历

        3. 是一个无序的集合,存储元素和取出元素的顺序有可能不一致

        4. 底层是一个哈希表结构(查询的速度非常的快)

    二、HashSet 集合存储数据的结构

      1、哈希值

        哈希值:是一个十进制的整数,由系统随机给出(就是对象的地址值,是一个逻辑地址,是模拟出来得到地址,不是数据实际存储的物理地址)

        在 Object 类中有一个方法,可以获取对象的哈希值。

        int hashCode() 返回该对象的哈希码值。

        hashCode 方法的源码:

    public native int hashCode();
    native:代表该方法调用的是本地操作系统的方法

      2、哈希表

        在 JDK1.8 之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。

        JDK1.8中(之后),哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。

         存储流程图:

         Demo:

      JDK1.8引入红黑树大程度优化了HashMap的性能,那么对于我们来讲保证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。如果我们往集合中存放自定义的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。

      3、Set 集合不允许存储重复元素的原理

    三、HashSet 存储自定义类型元素

      给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一。

      Demo:

     1 // 创建自定义 student 类
     2 public class Student {
     3     private String name;
     4     private int age;
     5 
     6     public Student() {
     7     }
     8 
     9     public Student(String name, int age) {
    10         this.name = name;
    11         this.age = age;
    12     }
    13 
    14     public String getName() {
    15         return name;
    16     }
    17 
    18     public void setName(String name) {
    19         this.name = name;
    20     }
    21 
    22     public int getAge() {
    23         return age;
    24     }
    25 
    26     public void setAge(int age) {
    27         this.age = age;
    28     }
    29 
    30     @Override
    31     public boolean equals(Object o) {
    32         if (this == o)
    33             return true;
    34         if (o == null || getClass() != o.getClass())
    35             return false;
    36         Student student = (Student) o;
    37         return age == student.age &&
    38                Objects.equals(name, student.name);
    39     }
    40 
    41     @Override
    42     public int hashCode() {
    43         return Objects.hash(name, age);
    44     }
    45 }
    46 // 创建测试类
    47 public class HashSetDemo2 {
    48     public static void main(String[] args) {
    49         //创建集合对象   该集合中存储 Student类型对象
    50         HashSet<Student> stuSet = new HashSet<Student>();
    51         //存储 
    52         Student stu = new Student("于谦", 43);
    53         stuSet.add(stu);
    54         stuSet.add(new Student("郭德纲", 44));
    55         stuSet.add(new Student("于谦", 43));
    56         stuSet.add(new Student("郭麒麟", 23));
    57         stuSet.add(stu);
    58 
    59         for (Student stu2 : stuSet) {
    60             System.out.println(stu2);
    61         }
    62     }
    63 }
    64 执行结果:
    65 Student [name=郭德纲, age=44]
    66 Student [name=于谦, age=43]
    67 Student [name=郭麒麟, age=23]
    View Code

    四、遍历集合

      1、增强 for 循环

    for (Integer i : set) {
         System.out.println(i);
    }

      2、迭代器遍历

    Iterator<Integer> it = set.iterator();
    while (it.hasNext()){
          Integer n = it.next();
          System.out.println(n); 
    }
    

      

  • 相关阅读:
    FreeTextbox 中吃掉Server路径的问题
    .net 中发mail到hotmail中乱码问题的解决
    管理的技巧和沟通
    将近一个星期都没来园子里面了
    园子里面西安的朋友请进来
    又开始乱了
    google真是个小人
    周末的晴天
    pm2入门
    strlen与sizeof区别 冷夜
  • 原文地址:https://www.cnblogs.com/niujifei/p/11439814.html
Copyright © 2020-2023  润新知