精华内容
下载资源
问答
  • java哈希表
    2021-09-30 23:14:55

    哈希表

    理想的情况是希望不经过任何比较,一次存取便能得到所查记录,那就必须在记录的存储位置和它的关键字之间建立一个确定的关系,使每个关键字和结构中一个唯一的存储位置相对应。因而在查找时,只要根据这个对应关系找到给定值的像。若结构中存在关键字和相等的记录,则必定在的存储位置上,反之在这个位置上没有记录。由此,不需要比较便可直接取得所查记录。在此,我们称这个对应关系为哈希(Hash)函数 ,按这个思想建立的表为哈希表

    import java.util.*;
    public class Main {
        
        public static void main(String[] args){
            
            HashMap <Integer,String> mp = new HashMap<Integer,String>();
            
            mp.put(1,"apple");
            mp.put(2,"google");
            mp.put(3,"netfix");
            
            
            System.out.println(mp); //输出所有哈希表中的元素
            System.out.println(mp.get(3));  //查询哈希表某一个键对应的元素
            System.out.println(mp.size());   //输出哈希表的大小
    
            //通过遍历键来查找所有值
            for(Integer i:mp.keySet())
            {
               System.out.println("key: "+i+",value: "+mp.get(i)); 
            }
            
            //直接遍历所有值
            for(String s:mp.values())
            {
                System.out.println("value: "+s); 
            }
    
            mp.clear(); //删除哈希表中所有元素
            System.out.println(mp); 
        }
    }
    
    更多相关内容
  • Java哈希表

    2022-04-06 16:41:22
    Java哈希表的介绍与实现

    目录

    概念

    冲突

    概念

    避免

    哈希函数设计

    负载因子调节

    解决

    闭散列

    开散列/哈希桶

    哈希冲突严重时的解决方法

    实现

    性能分析

    和java类集的关系


    概念

    如果构造一种存储结构,通过某种函数(hashFunc)使元素的存储位置与它的关键码之间能够建立一一映射的关系,那么在查找时通过该函数可以很快找到该元素。

    当向该结构中:

    插入元素:根据待插入元素的关键码,以此函数计算出该元素的存储位置并按此位置进行存放

    搜索元素:对元素的关键码进行同样的计算,把求得的函数值当做元素的存储位置,在结构中按此位置取元素比较,若关键码相等,则搜索成功

    该方式即为哈希(散列)方法,哈希方法中使用的转换函数称为哈希(散列)函数,构造出来的结构称为哈希表(HashTable)(或者称散列表)

    例如:数据集合{1,7,6,4,5,9};哈希函数设置为:hash(key) = key % capacity; capacity为存储元素底层空间总的大小。

    用该方法进行搜索不必进行多次关键码的比较,因此搜索的速度比较快。

    冲突

    概念

    对于两个数据元素的关键字 和 (i != j),有 != ,但有:Hash( ) == Hash( ),即:不同关键字通过相同哈希哈数计算出相同的哈希地址,该种现象称为哈希冲突或哈希碰撞。

    避免

    由于我们哈希表底层数组的容量往往是小于实际要存储的关键字的数量的,这就导致一个问题,冲突的发生是必然的,但我们能做的应该是尽量的降低冲突率。

    哈希函数设计

    引起哈希冲突的一个原因可能是:哈希函数设计不够合理

    1. 直接定制法

    取关键字的某个线性函数为散列地址:Hash(Key)= A*Key + B

    优点:简单、均匀

    缺点:需要事先知道关键字的分布情况

    使用场景:适合查找比较小且连续的情况

    2. 除留余数法

    设散列表中允许的地址数为m,取一个不大于m,但最接近或者等于m的质数p作为除数,按照哈希函数:Hash(key) = key% p(p将关键码转换成哈希地址

    所以,哈希函数设计的越精妙,产生哈希冲突的可能性就越低,但是无法避免哈希冲突

    负载因子调节

    负载因子和冲突率的关系粗略演示

    所以当冲突率达到一个无法忍受的程度时,我们需要通过降低负载因子来变相的降低冲突率

    已知哈希表中已有的关键字个数是不可变的,那我们能调整的就只有哈希表中的数组的大小

    解决

    解决哈希冲突两种常见的方法是:闭散列和开散列

    闭散列

    闭散列:也叫开放定址法,当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么可以把key存放到冲突位置中的“下一个” 空位置中去。

    线性探测

    二次探测

    研究表明:当表的长度为质数且表装载因子a不超过0.5时,新的表项一定能够插入,而且任何一个位置都不会被探查两次。因此只要表中有一半的空位置,就不会存在表满的问题。在搜索时可以不考虑表装满的情况,但在插入时必须确保表的装载因子a不超过0.5,如果超出必须考虑增容

    因此:闭散列最大的缺陷就是空间利用率比较低,这也是哈希的缺陷

    开散列/哈希桶

    开散列法又叫链地址法(开链法),首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。

    从上图可以看出,开散列中每个桶中放的都是发生哈希冲突的元素。

    开散列,可以认为是把一个在大集合中的搜索问题转化为在小集合中做搜索了

    哈希冲突严重时的解决方法

    刚才我们提到了,哈希桶其实可以看作将大集合的搜索问题转化为小集合的搜索问题了,那如果冲突严重,就意味着小集合的搜索性能其实也时不佳的,这个时候我们就可以将这个所谓的小集合搜索问题继续进行转化。

    例如:

    1. 每个桶的背后是另一个哈希表

    2. 每个桶的背后是一棵搜索树

    实现

    public class HashBuck {
        static class Node {
            public int key;
            public int val;
            public Node next;
    
            public Node(int key, int val) {
                this.key = key;
                this.val = val;
            }
        }
        public Node[] array;
    
        public int usedSize;//存放的数据的个数
    
        public static final double DEFAULT_LOAD_FACTOR = 0.75;//默认的负载因子
    
        public HashBuck () {
            array  = new Node[8];
        }
    
        public boolean put(int key,int val) {
    
            Node node = new Node(key,val);
            //1、位置
            int index = key % array.length;
    
            //2、遍历这个下标的链表
            Node cur = array[index];//就是一个链表的头节点
            while (cur != null) {
                if(cur.key == key) {
                    cur.val = val;//更新val值
                    return false;
                }
                cur = cur.next;
            }
            //3、遍历完成了当前下标的链表,开始进行插入
            node.next = array[index];
            array[index] = node;
            this.usedSize++;
            //4、存放元素之后,判断当前哈希桶当中的负载因子 是否超过了默认的负载因子
            if(loadFactor() >= DEFAULT_LOAD_FACTOR) {
                //5、扩容
                resize();
            }
            return true;
        }
    
        //扩容的同时 要进行重新哈希
        private void resize() {
            //1、重新申请2倍的数组
            Node[] tmp = new Node[array.length*2];
            //2、遍历原来的数组,把每个下标的链表的节点,都重新进行哈希
            for (int i = 0; i < array.length; i++) {
                Node cur = array[i];
                while (cur != null) {
                    int newIndex = cur.key % tmp.length;//新的数组的下标
                    Node curNext = cur.next;//先要记录下来下一个
                    cur.next = tmp[newIndex];
                    tmp[newIndex] = cur;
                    cur = curNext;//这里注意
                }
            }
            array = tmp;
        }
    
        public int get(int key) {
            //1、确定位置
            int index = key % array.length;
            Node cur = array[index];
            while (cur != null) {
                if(cur.key == key) {
                    return cur.val;
                }
                cur = cur.next;
            }
            return -1;
        }
        
        //计算当前哈希桶当中的负载因子
        private double loadFactor() {
            return this.usedSize*1.0 / this.array.length;
        }
    
    }

    我们还可以实现一个存放引用类型的哈希表

    public class HashBuck2<K,V> {
        static class Node<K,V> {
            public K key;
            public V val;
            public Node<K,V> next;
    
            public Node(K key,V val) {
                this.key = key;
                this.val = val;
            }
        }
        public Node<K,V>[] array = (Node<K,V>[])new Node[8];
    
        public int usedSize;
    
        public void put(K key,V val) {
            Node<K,V> node = new Node<>(key,val);
            int hash = key.hashCode();//可以把key变成一个整数
            int index = hash % array.length;
    
            Node<K,V> cur = array[index];
            while (cur != null) {
                if(cur.key.equals(key)) {
                    cur.val = val;//更新val值
                    return ;
                }
                cur = cur.next;
            }
            //3、遍历完成了当前下标的链表,开始进行插入
            node.next = array[index];
            array[index] = node;
            this.usedSize++;
        }
    
        public V get(K key) {
            int hash = key.hashCode();//可以把key变成一个整数
            int index = hash % array.length;
            Node<K,V> cur = array[index];
            while (cur != null) {
                if(cur.key.equals(key)) {
                    return cur.val;
                }
                cur = cur.next;
            }
            return null;
        }
    }

    性能分析

    虽然哈希表一直在和冲突做斗争,但在实际使用过程中,我们认为哈希表的冲突率是不高的,冲突个数是可控的,也就是每个桶中的链表的长度是一个常数,所以,通常意义下,我们认为哈希表的插入/删除/查找时间复杂度是O(1)

    和java类集的关系

    1. HashMap 和 HashSet 即 java 中利用哈希表实现的 Map 和 Set

    2. java 中使用的是哈希桶方式解决冲突的

    3. java 会在冲突链表长度大于一定阈值后,将链表转变为搜索树(红黑树)

    4. java 中计算哈希值实际上是调用的类的 hashCode 方法,进行 key 的相等性比较是调用 key 的equals 方法。所以如果要用自定义类作为 HashMap 的 key 或者 HashSet 的值,必须覆写 hashCode 和equals 方法,而且要做到 equals 相等的对象,hashCode 一定是一致的。

    展开全文
  • Java哈希表及其应用

    2022-02-23 09:46:30
    文章目录哈希表相关定义java哈希表的构造方法 哈希表相关定义 哈希表(hash table):也称散列表,是存储群体对象的集合类结构。是根据**键(Key)**而直接访问在内存存储位置的数据结构。也就是说,它通过计算一个...

    哈希表相关定义

    • 哈希表(hash table):也称散列表,是存储群体对象的集合类结构。是根据**键(Key)**而直接访问在内存存储位置的数据结构。也就是说,它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。这个映射函数称做散列函数,存放记录的数组称做散列表。
    • 关键字(key):key可以是对象本身,也可以是对象的一部分(如某个属性),在一个哈希表里每个关键字都必须是唯一的。
    • 值域(value):
    • 哈希码(Hash Code):若要将对象存储到Hashtable上,就需要将关键字Key映射到一个整型数据,成为Key的哈希码。
    • 项(item):Hash Table 的每一项都有两个域:关键字域(key)和值域(value:存储的对象)。key和value可以是任意Object型对象,但是不能为空。
    • 装填因子(Load Factor):

    java哈希表的构造方法

    哈希表的使用

    • Hashtable(); //默认构造函数,初始容量为101,最大填充因子0.75
    • Hashtable(int capacity);
    • Hashtable(int capacity,float loadFactory);

    哈希表的主要表示方法

    在这里插入图片描述

    Map map = new HashMap()与HashMap map = new HashMap()区别

    Map 是接口 不能实例化的 ,只能使用其实现类来实例化,即
    Map map=new Map();是错误的
    HashMap Map接口的实现类
    用接口定义比较灵活以后少改动,是OOP的好习惯。

    定义的时候用MAP实例化为HashMap,万一以后要改成Hashtable,产生的改动少。

    Map map=new HashMap(); 就是将map实例化成一个hashMap。这样做的好处是调用者不需要知道map具体的实现,map接口与具体实现的映射java帮你做了。打个比方,你是一个头头,手下有几个人:张三,李四等等。你需要手下做一件事情,你关心的是有没有人做,而不关心到底是谁去做,你只需要喊一声:“来人!”具体的是哪个人进来帮你做事无所谓。
    如果说这样写: HashMap map = new HashMap();就相当于你指定要张三做事:“来张三!”
    就是这样。

    关于Map的具体方法和变量, 具体参考官网API
    map具体方法描述

    原文:https://blog.csdn.net/Yan_Less/article/details/88819504?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164559730516780274133828%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164559730516780274133828&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-2-88819504.pc_search_result_cache&utm_term=hashmap+%3D+new+hashmap&spm=1018.2226.3001.4187

    展开全文
  • JAVA哈希表

    千次阅读 2021-03-08 18:47:52
    哈希表的定义 哈希表(Hash table,也叫散列表)是一种查找算法,与链表、树等算法不同的是,哈希表算法在查找时不需要进行一系列和关键字的比较操作。 哈希表算法希望能尽量做到不经过任何比较,通过一次存取就能...

    哈希表的定义

    哈希表(Hash table,也叫散列表)是一种查找算法,与链表、树等算法不同的是,哈希表算法在查找时不需要进行一系列和关键字的比较操作。
    哈希表算法希望能尽量做到不经过任何比较,通过一次存取就能得到所查找的数据元素,因而必 须要在数据元素的存储位置和它的关键字(可用key表示)之间建立一个确定的对应关系,使每个关键字和散列表中一个唯一的存储位置相对应。因此在查找时,只要根据这个对应关系找到给定 关键字在散列表中的位置即可。这种对应关系被称为哈希函数(可用H(key)表示)

    哈希函数的构造方法

    常用的哈希函数构造方法有:直接定址法、数字分析法、平方取中法、折叠法、随机数法和除留余数法。
    (1)直接寻址法:取关键字或关键字的某个线性函数值作为散列地址,即 H(key) = keyH(key) = a * key + b,其中 a 和 b 为常数(这种散列函数叫自身函数)。

    (2)数字分析法:分析一组数据,比如某班学生的出生年月日时发现出生年月日的前几位数字大体相同,这样的话,冲突的几率会很大,但是发现年月日的后几位表示月份和具体日期的数字差别较大,如果用后几位构成散列地址,则冲突的几率会明显降低。因此数字分析法是找出数字的规律,尽可能利用这些数字构造冲突几率低的散列地址。

    (3)平方取中法:先通过求关键字的平方值扩大相近的差别,然后根据表长度取中间的几位数作为散列函数值。又因为一个乘积的中间几位数和乘数的每一位都相关,所以由此产生的散列地址较为均匀。

    (4)除余法:该方法是最为简单常用的一种方法。它是以表长 m 来除关键字,取其余数作为散列地址,即 H(key) = key % m。该方法的关键是选取 m。选取的 m 应使得散列函数尽可能与关键字的各位相关。m 最好为素数。

    (5)相乘取整法:该方法包括两个步骤,首先用关键字 key 乘上某个常数 A(0 < A < 1),并抽取出 key.A 的小数部分;然后用 m 乘以该小数后取整

    处理冲突的方法:

    1. 开放定址法

    2. 链地址法

    3. 再哈希法

    4. 建立一个公共溢出区

    Hashtable的基本操作

    hashtable的初始容量是101
    hashtable是线程安全的,put( ),remove( )方法等都有synchronized,所有效率不如hashmap。

    public class Hashdemo {
        public static void main(String[] args) {
            Hashtable<Integer,String> hashtable=new Hashtable<>();
            //存储键值对,键和值都不允许为空
            hashtable.put(3,"张三");
            hashtable.put(4,"李四");
            hashtable.put(5,"王五");
            hashtable.put(6,"赵六");
            System.out.println(hashtable);
            //判断哈希表是否包含给定关键字
            System.out.println("key:2 :"+hashtable.containsKey(2));
            System.out.println("key:3 :"+hashtable.containsKey(3));
            //判断哈希表是否包含给定的对象
            System.out.println("value:张三 :"+hashtable.contains("张三"));
            System.out.println("value:小明 :"+hashtable.contains("小明"));
            //根据关键字删除对象
            hashtable.remove(4);
            System.out.println("after remove"+hashtable);
            //遍历哈希表
            Iterator<Integer> iterator=hashtable.keySet().iterator();
            while (iterator.hasNext()){
                Integer key=iterator.next();
                System.out.println(key+"--"+hashtable.get(key));
            }
        }
    }
    
    
    展开全文
  • java哈希表根据value值排序实例源码:/*** 功能:排序并输出*/private static void outputRegionStatistics(HashMap regionMap){ArrayList> mappingList = new ArrayList>(regionMap.entrySet());//通过比较器...
  • JAVA哈希表常用操作

    2022-03-09 16:17:13
    1.创建哈希表 String[] hashTable = new String[4]; //用数组创建哈希表 4代表创建容纳四个String类型的数组 HashMap<Integer , String > map = new HashMap<>(); //用HashMap创建哈希表 Integer...
  • Java哈希表及链式哈希表的实现

    千次阅读 2019-06-18 14:40:02
    哈希表也称为散列表,是用来存储群体对象的集合类结构。 什么是哈希表 数组和向量都可以存储对象,但对象的存储位置是随机的,也就是说对象本身与其存储位置之间没有必然的联系。当要查找一个对象时,只能以某种...
  • 文章目录Java哈希表概念冲突避免冲突哈希函数的设计方法常见哈希函数负载因子调节解决哈希冲突两种常见的方法是:闭散列和开散列哈希表和 java 类集的关系 Java哈希表 概念 顺序结构以及平衡树中,元素关键码与其...
  • 1.创建哈希表 创建哈希表有两种方式:数组;HashMap //数组,索引作为key值 String[] hashTable = new String[4]; //HashMap HashMap<Integer,String> map = new HashMap<>(); 2.添加元素 //数组 ...
  • 主要介绍了哈希表HashMap的深入学习,哈希表是一种非常重要的数据结构,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表,本文会对java集合框架中HashMap的实现原理进行讲解。感兴趣的话可以...
  • Java 哈希表

    2020-03-03 23:36:36
    本文介绍了 Java哈希表(HashSet 和 HashMap 集合存储数据的结构)的相关内容。。。
  • 哈希表Java 用于学习目的的Java哈希表程序
  • java 哈希表入门

    2021-03-17 20:53:51
    Java哈希表(Hash Table) 最近做题经常用到哈希表来进行快速查询,遂记录Java是如何实现哈希表的。这里只简单讲一下利用Map和HashMap实现哈希表。 首先,什么是Map和HashMap? Map<K, V>是一个以键值(Key)-...
  • Java哈希表(Hash Table)

    千次阅读 2020-10-28 12:49:08
    Java哈希表(Hash Table) 最近做题经常用到哈希表来进行快速查询,遂记录Java是如何实现哈希表的。这里只简单讲一下利用Map和HashMap实现哈希表。 首先,什么是Map和HashMap? Map<K, V>是一个以键值(Key)-...
  • Java实现哈希表

    千次阅读 2022-04-26 14:00:03
    哈希表也叫散列表,是根据关键码值(key-value)而进行直接访问的数据结构。它通过把关键码值映射到表中的某一位置来访问记录,这个映射函数叫做散列函数,存放记录的数组叫散列表。 哈希表可以用数组+链表来实现,也...
  • JAVA——哈希表

    千次阅读 2022-03-02 18:05:57
    1、HashMap集合底层是哈希表/散列表的数据结构。 2、哈希表是一个怎样的数据结构呢? 哈希表是一个数组和单向链表的结合体。 数组:在查询方面效率很高,随机增删方面效率很低。 单向链表:在随机增删方面效率较...
  • 1、哈希表的基本介绍 哈希表(Hash table,也叫散列表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中的一个位置来访问记录,以加快查找的速度。这个映射函数叫做...
  • 一、哈希表简介 散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,...
  • 哈希表Java实现)

    千次阅读 2022-02-04 10:31:51
    哈希表Java实现)
  • Java基础-哈希表

    千次阅读 2020-09-11 15:26:27
    哈希表(Hash table,也叫散列表): 是根据关键码值(Key value)而直接进行访问的数据结构。 也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的...
  • Java哈希表性能优化

    2014-01-26 17:08:57
    Java哈希表性能优化
  • Java哈希表操作

    2022-03-14 14:48:49
    import java.util.HashMap; public class HashTableTest { ... // 通过Array创建哈希表 String[] hashTable = new String[4]; // 通过HashMap库创建哈希表 HashMap<Integer, String> map = new HashMap<
  • 文章目录哈希表概念哈希函数的构造平均数取中法折叠法保留余数法哈希冲突问题以及解决方法开放地址法再哈希函数法公共溢出区法链式地址法哈希表的填充因子代码实现哈希函数添加数据删除数据判断哈希表是否为空遍历...
  • Java简单实现链式哈希表

    千次阅读 2022-02-03 16:08:05
    文章目录什么是哈希表试题代码输出结果 什么是哈希表 散列表(Hash table 也叫哈希表),是通过关键码值(key value)而直接进行访问的数据结构。也就是说,它通过关键码值映射到表中的一个位置来访问记录,以加快...
  • JDK8之前,底层采用“数组+链表”实现哈希表。而在JDK8之后,底层做了优化。 由于HashSet实质是使用Set接口的类,因此需要遵循Set接口的特征: Set集合特点: (1)不可以拥有重复元素 (2)没有带索引方法,不能...
  • JAVA--哈希表

    2022-03-14 23:37:12
    哈希表是一种以键值key存储数据value的结构,以key作为标识值存储value值;只要输入待查找的key,即可获取其对应的value值 思路很简单,所有的key的hashcode值都是整数,那么就可以使用一个简单的数组来实现:将key...
  • Java哈希表理解丶代码实现

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 188,302
精华内容 75,320
关键字:

java哈希表