大数据之什么是Hash表

简介:   大数据之什么是Hash表,Hash,一般翻译做“散列”,也有直接音译为“哈希”的,它是基于快速存取的角度设计的,也是一种典型的“空间换时间”的做法。顾名思义,该数据结构可以理解为一个线性表,但是其中的元素不是紧密排列的,而是可能存在空隙。

  大数据之什么是Hash表,Hash,一般翻译做“散列”,也有直接音译为“哈希”的,它是基于快速存取的角度设计的,也是一种典型的“空间换时间”的做法。顾名思义,该数据结构可以理解为一个线性表,但是其中的元素不是紧密排列的,而是可能存在空隙。

​ 散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。比如我们存储70个元素,但我们可能为这70个元素申请了100个元素的空间。70/100=0.7,这个数字称为负载(加载)因子。我们之所以这样做,也 是为了“快速存取”的目的。我们基于一种结果尽可能随机平均分布的固定函数H为每个元素安排存储位置,以达到快速存取。但是由于此随机性,也必然导致一个问题就是冲突。所谓冲突,即两个元素通过散列函数H得到的地址相同,那么这两个元素称为“同义词”。这类似于70个人去一个有100个椅子的饭店吃饭。散列函数的计算结果是一个存储单位地址,每个存储单位称为“桶”。设一个散列表有m个桶,则散列函数的值域应为[0,m-1]。

  这些元素是按照什么样的规则存储到数组中呢。一般情况是通过hash(key)%len获得,也就是元素的key的哈希值对数组长度取模得到。比如上述哈希表中,12%16=12,28%16=12,108%16=12,140%16=12。所以12、28、108以及140都存储在数组下标为12的位置

2.hash表扩容的理解

可是当哈希表接近装满时,因为数组的扩容问题,性能较低(转移到更大的哈希表中).

Java默认的散列单元大小全部都是2的幂,初始值为16(2的4次幂)。假如16条链表中的75%链接有数据的时候,则认为加载因子达到默认的0.75。HahSet开始重新散列,也就是将原来的散列结构全部抛弃,重新开辟一个散列单元大小为32(2的5次幂)的散列结果,并重新计算各个数据的存储位置。以此类推下去.....

负载(加载)因子:0.75.-->hash表提供的空间是16 也就是说当到达12的时候就扩容

3.排重机制的实现

假如我们有一个数据(散列码76268),而此时的HashSet有128个散列单元,那么这个数据将有可能插入到数组的第108个链表中(76268%128=108)。但这只是有可能,如果在第108号链表中发现有一个老数据与新数据equals()=true的话,这个新数据将被视为已经加入,而不再重复丢入链表。

4.优点

哈希表的插入和查找是很优秀的.

对于查找:直接根据数据的散列码和散列表的数组大小计算除余后,就得到了所在数组的位置,然后再查找链表中是否有这个数据即可。因为数组本身查找速度快,所以查找的效率高低体现在链表中,但是真实情况下在一条链表中的数据又很少,有的甚至没有,所以几乎没有什么迭代的代价。所以散列表的查找效率建立在散列单元所指向的链表中数据的多少上.

对于插入:数组的插入速度慢,而链表的插入速度快.当我们使用哈希表时,不需要更改数组的结构,只需要在找到对应的数组下标后,进入对应的链表,操作链表即可.所以hash表的整体插入速度也很快.

5.模拟实现代码

Node类

public class Node {
// key、value模拟键值对的数据
    public Integer key;
    public String value;
    // 下一节点的引用
    public Node next;
    public Node() {
    }
    public Node(int key, String value) {
        this.key = key;
        this.value = value;
    }
 
}

MyLinkedList类

    public class MyLinkedList {
    // 根节点
    private Node root;
 
    public MyLinkedList() {
        root = new Node();
    }
    /**
     * 添加数据,key值必须唯一,如果重复值将被覆盖
     * @param key
     */
    public void add(int key, String value) {
 
        Node newNode = new Node(key, value);
        Node current = root;
        while (current.next != null) {
            if(current.next.key == key) {
                current.next.value = value;
                return;
            }
            current = current.next;
        }
        current.next = newNode;
    }
 
    /**
     * 删除数据
     * @param key
     * @return
     */
    public boolean delete(int key) {
 
        Node current = root;
        while (current.next != null) {
            if(current.next.key == key) {
                current.next = current.next.next;
                return true;
            }
            current = current.next;
        }
        return false;
    }
 
    /**
     * 根据key获取value
     * @param key
     * @return
     */
    public String get(int key) {
 
        Node current = root;
        while (current.next != null) {
            if(current.next.key == key) {
                return current.next.value;
            }
            current = current.next;
        }
        return null;
    }
 
    /**
     * 遍历链表,列出所有数据
     * @return
     */
    public String list() {
 
        String str = "";
        Node current = root.next;
        while (current != null) {
            str += "(" + current.key + "," + current.value + "),";
            current = current.next;
        }
        return str;
    }
 
    @Override
    public String toString() {
        return list();
    }
}

MyHashMap类

// 哈希表
public class MyHashMap {
 
    // 链表数组,数组的每一项都是一个链表
    private MyLinkedList[] arr;
    // 数组的大小
    private int maxSize;
 
    /**
     * 空参构造,默认数组大小为10
     */
    public MyHashMap() {
        maxSize = 10;
        arr = new MyLinkedList[maxSize];
    }
 
    /**
     * 带参构造,数组大小自定义
     * @param maxSize
     */
    public MyHashMap(int maxSize) {
        this.maxSize = maxSize;
        arr = new MyLinkedList[maxSize];
    }
 
    /**
     * 添加数据,key值必须唯一
     * @param key
     * @param value
     */
    public void put(int key, String value) {
 
        int index = getHashIndex(key);
        if(arr[index] == null) {
            arr[index] = new MyLinkedList();
        }
        arr[index].add(key, value);
    }
 
    /**
     * 删除数据
     * @param key
     * @return
     */
    public boolean delete(int key) {
 
        int index = getHashIndex(key);
        if(arr[index] != null) {
            return arr[index].delete(key);
        }
        return false;
    }
 
    /**
     * 根据key获取value
     * @param key
     * @return
     */
    public String get(int key) {
 
        int index = getHashIndex(key);
        if(arr[index] != null) {
            return arr[index].get(key);
        }
        return null;
    }
 
    /**
     * 获取数组下标
     * @param key
     * @return
     */
    private int getHashIndex(Integer key) {
        return key.hashCode() % maxSize;
    }
 
    /**
     * 遍历数组中所有链表的数据
     * @return
     */
    public String list() {
 
        String str = "[ ";
        for (int i = 0; i < maxSize; i++) {
            if(arr[i] != null) {
                str += arr[i].toString();
            }
        }
        str = str.substring(0, str.length()-1);
        str += " ]";
        return str;
    }
 
    @Override
    public String toString() {
        return list();
    }
}

测试类

public class Test {
 
    public static void main(String[] args) {
 
        MyHashMap map = new MyHashMap(20);
 
        map.put(5, "aaa");
        map.put(8, "bbb");
        map.put(3, "ccc");
        map.put(8, "bbb");
        map.put(2, "ddd");
        map.put(9, "eee");
 
        System.out.println(map);
        System.out.println(map.get(3));
        System.out.println(map.delete(2));
        System.out.println(map);
    }
}
相关实践学习
简单用户画像分析
本场景主要介绍基于海量日志数据进行简单用户画像分析为背景,如何通过使用DataWorks完成数据采集 、加工数据、配置数据质量监控和数据可视化展现等任务。
SaaS 模式云数据仓库必修课
本课程由阿里云开发者社区和阿里云大数据团队共同出品,是SaaS模式云原生数据仓库领导者MaxCompute核心课程。本课程由阿里云资深产品和技术专家们从概念到方法,从场景到实践,体系化的将阿里巴巴飞天大数据平台10多年的经过验证的方法与实践深入浅出的讲给开发者们。帮助大数据开发者快速了解并掌握SaaS模式的云原生的数据仓库,助力开发者学习了解先进的技术栈,并能在实际业务中敏捷的进行大数据分析,赋能企业业务。 通过本课程可以了解SaaS模式云原生数据仓库领导者MaxCompute核心功能及典型适用场景,可应用MaxCompute实现数仓搭建,快速进行大数据分析。适合大数据工程师、大数据分析师 大量数据需要处理、存储和管理,需要搭建数据仓库?学它! 没有足够人员和经验来运维大数据平台,不想自建IDC买机器,需要免运维的大数据平台?会SQL就等于会大数据?学它! 想知道大数据用得对不对,想用更少的钱得到持续演进的数仓能力?获得极致弹性的计算资源和更好的性能,以及持续保护数据安全的生产环境?学它! 想要获得灵活的分析能力,快速洞察数据规律特征?想要兼得数据湖的灵活性与数据仓库的成长性?学它! 出品人:阿里云大数据产品及研发团队专家 产品 MaxCompute 官网 https://www.aliyun.com/product/odps&nbsp;
相关文章
|
10月前
|
SQL 数据采集 算法
大数据到底应该如何学?
大数据到底应该如何学?
81 0
|
存储 数据采集 分布式计算
大数据能做什么?
大数据能做什么?
179 0
大数据能做什么?
|
大数据 数据库
大数据使“定制”新的经济指标成为可能
大数据使“定制”新的经济指标成为可能
109 0
大数据使“定制”新的经济指标成为可能
|
存储 分布式计算 大数据
什么是大数据?
  然而,什么是大数据?至今也没有一个比较权威的定义。   麦肯锡曾给出大数据的定义是:大数据是指大小超出了常规数据库工具获取、存储、管理和分析能力的数据集合。   维基百科也给出类似的定义:大数据指的是所涉及的数据量规模大到无法通过目前主流软件工具,在合理时间内达到撷取、管理、处理并整理成为帮助企业经营决策更积极目的的资讯。   一句话,大数据就是数据量大?!   我觉得,这句话说了等于没说,还容易让人误解。你以为数据量大才是大数据?
337 0
|
大数据 分布式计算 Hadoop
从0到1完全掌握大数据
经常听别人说“我要去学习大数据”,乍一听大数据应该是某个技术。而通俗来讲,大数据就是大到难以处理的数据集合,是社会技术发展过程中碰到的棘手问题。本文将从大数据的由来和相关技术分别展开进行讲解,从0到1系统地介绍如何学会使用大数据。
3129 0
|
分布式计算 大数据 Java
|
人工智能 大数据 物联网
想学大数据,从哪里开始比较好
本人目前从事网站运营方面的工作,懂一丢丢html代码,英语水平为0, 英语目前正在学,兼职学了半年多了,明年准备辞职出来全职学,应该明年在用大半年时间能搞定。英语学好后准备进入大数据行业。 不知道从哪里开始,希望得到一些路线指导。
2025 0