Murmurhash 哈希算法 介绍与实现

2023-11-04

最近在项目代码中看到了一种hash算法,以前没有遇见过,在此记录下来。
 

一、介绍

  MurmurHash 是一种非加密型哈希函数,适用于一般的哈希检索操作。 由Austin Appleby在2008年发明, 并出现了多个变种,都已经发布到了公有领域(public domain)。与其它流行的哈希函数相比,对于规律性较强的key,MurmurHash的随机分布特征表现更良好。—摘自wiki

  Redis在实现字典时用到了两种不同的哈希算法,MurmurHash便是其中一种(另一种是djb),在Redis中应用十分广泛,包括数据库、集群、哈希键、阻塞操作等功能都用到了这个算法。发明算法的作者被邀到google工作,该算法最新版本是MurmurHash3,基于MurmurHash2改进了一些小瑕疵,使得速度更快,实现了32位(低延时)、128位HashKey,尤其对大块的数据,具有较高的平衡性与低碰撞率。
 

二、代码

代码来自GitHub: https://github.com/aappleby/smhasher
因为Murmurhash最新版本是MurmurHash3,这里只简单测试了一下MurmurHash3

Murmurhash3.h

//-----------------------------------------------------------------------------
// MurmurHash3 was written by Austin Appleby, and is placed in the public
// domain. The author hereby disclaims copyright to this source code.
 
#ifndef _MURMURHASH3_H_
#define _MURMURHASH3_H_
 
//-----------------------------------------------------------------------------
// Platform-specific functions and macros
 
// Microsoft Visual Studio
 
#if defined(_MSC_VER) && (_MSC_VER < 1600)
 
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
typedef unsigned __int64 uint64_t;
 
// Other compilers
 
#else   // defined(_MSC_VER)
 
#include <stdint.h>
 
#endif // !defined(_MSC_VER)
 
//-----------------------------------------------------------------------------
 
void MurmurHash3_x86_32  ( const void * key, int len, uint32_t seed, void * out );
 
void MurmurHash3_x86_128 ( const void * key, int len, uint32_t seed, void * out );
 
void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * out );
 
//-----------------------------------------------------------------------------
 
#endif // _MURMURHASH3_H_

Murmurhash3.c

//-----------------------------------------------------------------------------
// MurmurHash3 was written by Austin Appleby, and is placed in the public
// domain. The author hereby disclaims copyright to this source code.
 
// Note - The x86 and x64 versions do _not_ produce the same results, as the
// algorithms are optimized for their respective platforms. You can still
// compile and run any of them on any platform, but your performance with the
// non-native version will be less than optimal.
// 
// github : https://github.com/aappleby/smhasher
 
#include "MurmurHash3.h"
 
//-----------------------------------------------------------------------------
// Platform-specific functions and macros
 
// Microsoft Visual Studio
 
#if defined(_MSC_VER)
 
#define FORCE_INLINE    __forceinline
 
#include <stdlib.h>
 
#define ROTL32(x,y) _rotl(x,y)
#define ROTL64(x,y) _rotl64(x,y)
 
#define BIG_CONSTANT(x) (x)
 
// Other compilers
 
#else   // defined(_MSC_VER)
#define FORCE_INLINE inline __attribute__((always_inline))
 
inline static uint32_t rotl32 ( uint32_t x, int8_t r )
{
    return (x << r) | (x >> (32 - r));
}
 
inline static uint64_t rotl64 ( uint64_t x, int8_t r )
{
    return (x << r) | (x >> (64 - r));
}
 
#define ROTL32(x,y) rotl32(x,y)
#define ROTL64(x,y) rotl64(x,y)
 
#define BIG_CONSTANT(x) (x##LLU)
 
#endif // !defined(_MSC_VER)
 
//-----------------------------------------------------------------------------
// Block read - if your platform needs to do endian-swapping or can only
// handle aligned reads, do the conversion here
 
FORCE_INLINE uint32_t getblock32 ( const uint32_t * p, int i )
{
    return p[i];
}
 
FORCE_INLINE uint64_t getblock64 ( const uint64_t * p, int i )
{
    return p[i];
}
 
//-----------------------------------------------------------------------------
// Finalization mix - force all bits of a hash block to avalanche
 
FORCE_INLINE uint32_t fmix32 ( uint32_t h )
{
    h ^= h >> 16;
    h *= 0x85ebca6b;
    h ^= h >> 13;
    h *= 0xc2b2ae35;
    h ^= h >> 16;
 
    return h;
}
 
//----------
 
FORCE_INLINE uint64_t fmix64 ( uint64_t k )
{
    k ^= k >> 33;
    k *= BIG_CONSTANT(0xff51afd7ed558ccd);
    k ^= k >> 33;
    k *= BIG_CONSTANT(0xc4ceb9fe1a85ec53);
    k ^= k >> 33;
 
    return k;
}
 
//-----------------------------------------------------------------------------
 
void MurmurHash3_x86_32 ( const void * key, int len,
    ¦   uint32_t seed, void * out )
{
    const uint8_t * data = (const uint8_t*)key;
    const int nblocks = len / 4;
 
    uint32_t h1 = seed;
 
    const uint32_t c1 = 0xcc9e2d51;
    const uint32_t c2 = 0x1b873593;
 
    //----------
    // body
 
    const uint32_t * blocks = (const uint32_t *)(data + nblocks*4);
 
    for(int i = -nblocks; i; i++)
    {
        uint32_t k1 = getblock32(blocks,i);
 
        k1 *= c1;
        k1 = ROTL32(k1,15);
        k1 *= c2;
 
        h1 ^= k1;
        h1 = ROTL32(h1,13);
        h1 = h1*5+0xe6546b64;
    }
 
    //----------
    // tail
 
    const uint8_t * tail = (const uint8_t*)(data + nblocks*4);
 
    uint32_t k1 = 0;
 
    switch(len & 3)
    {
        case 3: k1 ^= tail[2] << 16;
        case 2: k1 ^= tail[1] << 8;
        case 1: k1 ^= tail[0];
                k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
    };
 
    //----------
    // finalization
 
    h1 ^= len;
 
    h1 = fmix32(h1);
 
    *(uint32_t*)out = h1;
}
 
//-----------------------------------------------------------------------------
 
void MurmurHash3_x86_128 ( const void * key, const int len,
        uint32_t seed, void * out )
{
    const uint8_t * data = (const uint8_t*)key;
    const int nblocks = len / 16;
 
    uint32_t h1 = seed;
    uint32_t h2 = seed;
    uint32_t h3 = seed;
    uint32_t h4 = seed;
 
    const uint32_t c1 = 0x239b961b;
    const uint32_t c2 = 0xab0e9789;
    const uint32_t c3 = 0x38b34ae5;
    const uint32_t c4 = 0xa1e38b93;
 
    //----------
    // body
 
    const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);
 
    for(int i = -nblocks; i; i++)
    {
        uint32_t k1 = getblock32(blocks,i*4+0);
        uint32_t k2 = getblock32(blocks,i*4+1);
        uint32_t k3 = getblock32(blocks,i*4+2);
        uint32_t k4 = getblock32(blocks,i*4+3);
 
        k1 *= c1; k1  = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
 
        h1 = ROTL32(h1,19); h1 += h2; h1 = h1*5+0x561ccd1b;
 
        k2 *= c2; k2  = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
 
        h2 = ROTL32(h2,17); h2 += h3; h2 = h2*5+0x0bcaa747;
 
        k3 *= c3; k3  = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
 
        h3 = ROTL32(h3,15); h3 += h4; h3 = h3*5+0x96cd1c35;
 
        k4 *= c4; k4  = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
 
        h4 = ROTL32(h4,13); h4 += h1; h4 = h4*5+0x32ac3b17;
    }
 
    //----------
    // tail
 
    const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
 
    uint32_t k1 = 0;
    uint32_t k2 = 0;
    uint32_t k3 = 0;
    uint32_t k4 = 0;
 
    switch(len & 15)
    {
        case 15: k4 ^= tail[14] << 16;
        case 14: k4 ^= tail[13] << 8;
        case 13: k4 ^= tail[12] << 0;
                 k4 *= c4; k4  = ROTL32(k4,18); k4 *= c1; h4 ^= k4;
 
        case 12: k3 ^= tail[11] << 24;
        case 11: k3 ^= tail[10] << 16;
        case 10: k3 ^= tail[ 9] << 8;
        case  9: k3 ^= tail[ 8] << 0;
                 k3 *= c3; k3  = ROTL32(k3,17); k3 *= c4; h3 ^= k3;
 
        case  8: k2 ^= tail[ 7] << 24;
        case  7: k2 ^= tail[ 6] << 16;
        case  6: k2 ^= tail[ 5] << 8;
        case  5: k2 ^= tail[ 4] << 0;
                 k2 *= c2; k2  = ROTL32(k2,16); k2 *= c3; h2 ^= k2;
 
        case  4: k1 ^= tail[ 3] << 24;
        case  3: k1 ^= tail[ 2] << 16;
        case  2: k1 ^= tail[ 1] << 8;
        case  1: k1 ^= tail[ 0] << 0;
                 k1 *= c1; k1  = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
    };
 
    //----------
    // finalization
 
    h1 ^= len; h2 ^= len; h3 ^= len; h4 ^= len;
 
    h1 += h2; h1 += h3; h1 += h4;
    h2 += h1; h3 += h1; h4 += h1;
 
    h1 = fmix32(h1);
    h2 = fmix32(h2);
    h3 = fmix32(h3);
    h4 = fmix32(h4);
 
    h1 += h2; h1 += h3; h1 += h4;
    h2 += h1; h3 += h1; h4 += h1;
 
    ((uint32_t*)out)[0] = h1;
    ((uint32_t*)out)[1] = h2;
    ((uint32_t*)out)[2] = h3;
    ((uint32_t*)out)[3] = h4;
}
 
//-----------------------------------------------------------------------------
 
void MurmurHash3_x64_128 ( const void * key, const int len,
        const uint32_t seed, void * out )
{
    const uint8_t * data = (const uint8_t*)key;
    const int nblocks = len / 16;
 
    uint64_t h1 = seed;
    uint64_t h2 = seed;
 
    const uint64_t c1 = BIG_CONSTANT(0x87c37b91114253d5);
    const uint64_t c2 = BIG_CONSTANT(0x4cf5ad432745937f);
 
    //----------
    // body
 
    const uint64_t * blocks = (const uint64_t *)(data);
 
    for(int i = 0; i < nblocks; i++)
    {
        uint64_t k1 = getblock64(blocks,i*2+0);
        uint64_t k2 = getblock64(blocks,i*2+1);
 
        k1 *= c1; k1  = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
 
        h1 = ROTL64(h1,27); h1 += h2; h1 = h1*5+0x52dce729;
 
        k2 *= c2; k2  = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
 
        h2 = ROTL64(h2,31); h2 += h1; h2 = h2*5+0x38495ab5;
    }
 
    //----------
    // tail
 
    const uint8_t * tail = (const uint8_t*)(data + nblocks*16);
 
    uint64_t k1 = 0;
    uint64_t k2 = 0;
 
    switch(len & 15)
    {
        case 15: k2 ^= ((uint64_t)tail[14]) << 48;
        case 14: k2 ^= ((uint64_t)tail[13]) << 40;
        case 13: k2 ^= ((uint64_t)tail[12]) << 32;
        case 12: k2 ^= ((uint64_t)tail[11]) << 24;
        case 11: k2 ^= ((uint64_t)tail[10]) << 16;
        case 10: k2 ^= ((uint64_t)tail[ 9]) << 8;
        case  9: k2 ^= ((uint64_t)tail[ 8]) << 0;
                 k2 *= c2; k2  = ROTL64(k2,33); k2 *= c1; h2 ^= k2;
 
        case  8: k1 ^= ((uint64_t)tail[ 7]) << 56;
        case  7: k1 ^= ((uint64_t)tail[ 6]) << 48;
        case  6: k1 ^= ((uint64_t)tail[ 5]) << 40;
        case  5: k1 ^= ((uint64_t)tail[ 4]) << 32;
        case  4: k1 ^= ((uint64_t)tail[ 3]) << 24;
        case  3: k1 ^= ((uint64_t)tail[ 2]) << 16;
        case  2: k1 ^= ((uint64_t)tail[ 1]) << 8;
        case  1: k1 ^= ((uint64_t)tail[ 0]) << 0;
                 k1 *= c1; k1  = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
    };
 
    //----------
    // finalization
 
    h1 ^= len; h2 ^= len;
 
    h1 += h2;
    h2 += h1;
 
    h1 = fmix64(h1);
    h2 = fmix64(h2);
 
    h1 += h2;
    h2 += h1;
 
    ((uint64_t*)out)[0] = h1;
    ((uint64_t*)out)[1] = h2;
}
 
//-----------------------------------------------------------------------------
#if 1
 
#include <string.h>
#include <stdio.h>
#define SEED 0x97c29b3a
 
int main()
{
    const char *str="abcdefghijklmn";
 
    uint32_t out1;
    MurmurHash3_x86_32(str, strlen(str), SEED, &out1);
    printf("%u\n", out1);
 
    uint32_t out2[4];
    MurmurHash3_x86_128(str, strlen(str), SEED, out2);
    printf("%u, %u, %u, %u\n", out2[0], out2[1], out2[2], out2[3]);
 
    uint64_t out3[2];
    MurmurHash3_x64_128(str, strlen(str), SEED, out3);
    printf("%lu, %lu\n", out3[0], out3[1]);
 
    return 0;
}
 
#endif

MurmurHash3_x86_32 将key 哈希32位的正整数
MurmurHash3_x86_128 将key 哈希128位的4个无符号位32整数,x86是32位的
MurmurHash3_x64_128 将key 哈希128位的2个无符号64位整数,x64是64位的

编译: gcc -std=c99 MurmurHash3.c MurmurHash3.h -o MurmurHash3

注意: 直接从GitHub拉取的代码在Linux可能编译不过去。
问题是在定义rotl32() 和rotl64()使用关键字inline,要么把inline去掉,要么在inline后面加关键字static.

 
 
 
 
 
 
 
关注公众号"小败日记",搬砖过程遇到的问题,大家一起探讨,资源共享

小败日记公众号

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Murmurhash 哈希算法 介绍与实现 的相关文章

  • 如何使用MemoryCache代替Timer来触发一个方法?

    以下方法通过等待已运行操作的结果来处理并发请求 对数据的请求可能会使用相同 不同的凭据同时出现 对于每组唯一的凭据 最多可以有一个GetCurrentInternal呼叫正在进行中 当准备就绪时 该呼叫的结果将返回给所有排队的服务员 pri
  • 如何读取扩展文件属性/文件元数据

    因此 我按照教程使用 ASP net core 将文件 上传 到本地路径 这是代码 public IActionResult About IList
  • C++ 中本地类中的静态成员变量?

    我知道我们不能宣布static本地类中的成员变量 但其原因尚不清楚 那么请问有人可以解释一下吗 另外 为什么我们不能访问非static函数内部定义的变量 内部已经定义了局部类 直接在局部类成员函数中 在下面给出的代码中 int main i
  • 为 Visual Studio 2013 编译 Tesseract

    我正在尝试使用tesseract在 Visual Studio 2013 中 我在链接器 gt 输入 不是 libtesseract302 static lib 中使用 libtesseract302 lib 一切都正常 并且已编译并运行
  • 向 Nhibernate 发出 SQL 查询

    如何将此 SQL 查询发送给 Nhibernate SELECT Customer name FROM Company INNER JOIN Customer ON Company CompanyId Customer CompanyId
  • 如何修复此错误“GDI+ 中发生一般错误”?

    从默认名称打开图像并以默认名称保存 覆盖它 我需要从 Image Default jpg 制作图形 将其放在 picturebox1 image 上并在 picurebox1 上绘制一些图形 它有效 这不是我的问题 但我无法保存 pictu
  • 在新的浏览器进程中打开 URL

    我需要在新的浏览器进程中打开 URL 当浏览器进程退出时我需要收到通知 我当前使用的代码如下 Process browser new Process browser EnableRaisingEvents true browser Star
  • XamlReader.Load 在后台线程中。是否可以?

    WPF 应用程序具有从单独的文件加载用户控件的操作 使用XamlReader Load method StreamReader mysr new StreamReader pathToFile DependencyObject rootOb
  • C++中的类查找结构体数组

    我正在尝试创建一个结构数组 它将输入字符串链接到类 如下所示 struct string command CommandPath cPath cPathLookup set an alarm AlarmCommandPath send an
  • 存储来自其他程序的事件

    我想将其他应用程序的事件存储在我自己的应用程序中 事件示例 打开 最小化 Word 或打开文件时 这样的事可能吗 运行程序 http msdn microsoft com en us library ms813609 aspx and 打开
  • 无法在 Windows 运行时组件库的 UserControl 中创建依赖项属性

    我想在用户控件内创建数据可绑定属性 这个用户控件包含一个 Windows 运行时组件 项目 我使用下面的代码来创建属性 public MyItem CurrentItem get return MyItem GetValue Current
  • 未经许可更改内存值

    我有一个二维数组 当我第一次打印数组的数据时 日期打印正确 但其他时候 array last i 的数据从 i 0 到 last 1 显然是一个逻辑错误 但我不明白原因 因为我复制并粘贴了 for 语句 那么 C 更改数据吗 I use g
  • 批量更新 SQL Server C#

    我有一个 270k 行的数据库 带有主键mid和一个名为value 我有一个包含中值和值的文本文件 现在我想更新表格 以便将每个值分配给正确的中间值 我当前的方法是从 C 读取文本文件 并为我读取的每一行更新表中的一行 必须有更快的方法来做
  • 上下文敏感与歧义

    我对上下文敏感性和歧义如何相互影响感到困惑 我认为正确的是 歧义 歧义语法会导致使用左推导或右推导构建多个解析树 所有可能的语法都是二义性的语言是二义性语言 例如 C 是一种不明确的语言 因为 x y 总是可以表示两个不同的事物 如下所述
  • 如何使用 Mongodb C# 驱动程序连接多个集合

    我需要将 3 个集合与多个集合合并在一起 lookup我在 C 驱动程序中尝试过 它允许我 lookup用户采集但无法执行秒 lookup用于设置集合 有人可以帮忙吗 db Transactions aggregate lookup fro
  • 私有模板函数

    我有一堂课 C h class C private template
  • 用于 C# 的 TripleDES IV?

    所以当我说这样的话 TripleDES tripledes TripleDES Create Rfc2898DeriveBytes pdb new Rfc2898DeriveBytes password plain tripledes Ke
  • Server.MapPath - 给定的物理路径,预期的虚拟路径

    我正在使用这行代码 var files Directory GetFiles Server MapPath E ftproot sales 在文件夹中查找文件 但是我收到错误消息说 给定物理路径但虚拟路径 预期的 我对在 C 中使用 Sys
  • 有没有办法强制显示工具提示?

    我有一个验证字段的方法 如果无法验证 该字段将被清除并标记为红色 我还希望在框上方弹出一个工具提示 并向用户显示该值无效的消息 有没有办法做到这一点 并且可以控制工具提示显示的时间 我怎样才能让它自己弹出而不是鼠标悬停时弹出 If the
  • 当另一个线程可能设置共享布尔标志(最多一次)时,是否可以读取共享布尔标志而不锁定它?

    我希望我的线程能够更优雅地关闭 因此我尝试实现一个简单的信号机制 我不认为我想要一个完全事件驱动的线程 所以我有一个工作人员有一种方法可以使用关键部分优雅地停止它Monitor 相当于C lock我相信 绘图线程 h class Drawi

随机推荐

  • 【工具】推荐一个开源小巧的pdf分析工具

    如何定位pdf的坐标 这是最近我遇到的问题 因为我需要把几个字类似水印通过java写到pdf上 搜了几个都说要用AcrobatCD软件 这个软件也下了但是发现并没有网格坐标的功能 不知道是不是要收费 还有就是gimp软件好像也能看pdf坐标
  • vue 发送ajax请求

    一 简介 1 vue本身不支持发送AJAX请求 需要使用vue resource vue1 0版本 axios vue2 0版本 等插件实现 2 axios是一个基于Promise的HTTP请求客户端 用来发送请求 也是vue2 0官方推荐
  • Functional Programming in Java venkat(15) Being Lazy part2

    Functional Programming in Java venkat 15 Being Lazy part2 这里是记录学习这本书 Functional Programming in Java Harnessing the Power
  • 双向可控硅

    转载于 http www baiheee com Documents 100830 100830085212 htm 双向可控硅是在单向可控硅的基础上发展起来的 顾名思义 它是 种具有双向导电特从外形上看双向可控硅和单向可控硅很相似 同样有
  • Qt绘制指针时钟

    Qt绘制指针时钟 什么是Qt Qt是一款跨平台的C 应用程序开发框架 它提供了一套完整的工具和库 可以帮助开发者快速构建高质量的应用程序 Qt支持多种操作系统和开发语言 包括Windows Linux macOS Android iOS等
  • spring boot学习(转)

    玩转Spring Boot 前言 首先在这里对Spring Boot做个简单的介绍 对Spring Boot也关注了挺久了 Spring Boot是由Pivotal团队提供的全新框架 Pivotal团队在2014年4月份发布第一个GA版本
  • SpringBoot学习笔记

    微服务阶段 JavaSE 面向对象 MySql JDBC 持久化存储 html css JavaScript Jquery 框架 视图 框架 JavaWeb 开始独立开发MVC三层架构的网站 原始 SSM 框架 简化了我们的开发流程 配置也
  • Lady General Hua Mu-lan花木兰剧本

    Lady General Hua Mu lan花木兰剧本 Gary专业版 Scene 0 Narrator N Oh come here little girl tell me do you want to become a woman a
  • 组件间通信方式

    方式一 props 适用于 父子组件间通信 1 父给子 父组件给子组件传递数据 非函数 本质其实是父组件 gt 子组件传递数据 父组件App vue
  • open/read/write和fopen/fread/fwrite的区别

    open read write和fopen fread fwrite的区别 open 系统调用 返回的是文件描述符 即文件句柄 是文件在文件描述副表里的索引 fopen C语言库函数 返回的是一个指向文件结构的指针 fopen是ANSI C
  • 进程之间为什么需要通信?

    进程是一个独立的资源分配单元 不同进程 这里所说的进程通常指的是用户进程 之间的资源是独立的 没有关联 不能在一个进程中直接访问另一个进程的资源 例如打开的文件描述符 但是 进程不是孤立的 不同的进程需要进行信息的交互和状态的传递等 因此需
  • 已解决io = ExcelFile(io,storage_options=storage.options, engine=engine)

    已解决 Python pandas read excel读取Excel文件报错 io ExcelFile io storage options storage options engine engine 文章目录 报错代码 报错原因 解决方
  • 渗透测试流程&信息收集

    渗透测试是一种评估方法 一种通过模拟黑客的攻击方式 来评估网站安全的方法 渗透测试流程分为7个阶段 信息收集 漏洞扫描 漏洞利用 内网转发 内网渗透 痕迹清除 编写报告 但在这7个阶段之前还有一个前提 就是授权 这个授权包括渗透测试的目标
  • Hbase Compaction 队列数量较大分析(压缩队列、刷新队列)

    前几天朋友公司Hbase集群出现Compaction队列持续处于比较大的情况 并且mem flush队列也比较大 一起看了下问题 大概情况如下图 从图中可以看出来压缩队列总和持续在1000 2000 平对压缩队列在200左右 刷新队列也比较
  • 三菱触摸屏怎么改时间_三菱plc的触摸屏程序,三菱触摸屏如何更改时间

    三菱plc的触摸屏程序 D8013D8014D8015D8016D8017D8018D8019秒 分钟 小时 日 月 年和周 假定上述时间需要改变 屏幕D10D11D12D13D14D15D16秒 分钟 天 月 年和周按钮M0程序LDM0设
  • Hive 用户自定义函数UDF详解

    本例自定义一个Hive UDF函数 功能是将从Hive数据仓库查询出来的字符串进行大小写转换 第一步 创建java工程 添加jar包 导入Hive的lib目录下的jar包以及hadoop安装目录下的hadoop core jar 第二步 新
  • RuoYi实现数据分页

    目录 一 实例简介 登录日志查询 数据分页作用 二 前端代码 1 打开操作日志页面源码文件 2 函数调用链 3 开发者工具查看前端访问后端信息 编辑 三 后端代码 函数startPage 和getDataTable 输出结果 一 实例简介
  • 栈 - 关于出栈序列,判断合法的出栈序列

    文章目录 1 引例 2 做题方法 3 原因 3 1 选项D 4 3 1 2 的模拟 1 引例 例 设栈的入栈序列是 1 2 3 4 则下列不可能是其出栈序列的是 A 1 2 4 3 B 2 1 3 4 C 1 4 3 2 D 4 3 1 2
  • MySQL数据库总体知识架构

    一 关系型数据库设计理论 一些重要术语 属性 attribute 列的名字 我们在开发中一般称为字段 依赖 relation 字段之间存在的关系 元祖 tuple 每一个行 如第二行 1301 小明 13班 篮球 英语 赵英 70 就是一个
  • Murmurhash 哈希算法 介绍与实现

    最近在项目代码中看到了一种hash算法 以前没有遇见过 在此记录下来 一 介绍 MurmurHash 是一种非加密型哈希函数 适用于一般的哈希检索操作 由Austin Appleby在2008年发明 并出现了多个变种 都已经发布到了公有领域