文档章节

哈希容器的使用

ruki
 ruki
发布于 2014/09/17 15:53
字数 971
阅读 178
收藏 6

stl的容器库非常强大,但是为了要兼容各种元素类型,采用了模板进行泛化,这样的好处就是使用非常的方便,但是编译器会对使用到的每种类型都进行一遍实例化,用的类型太多的话不仅影响编译速度而且生成的可执行文件也很冗余。

因此,TBOX在设计容器架构的时候,引入tb_item_func_t类型,来设置容器使用的成员类型,这样在实现容器通用性的同时,也不会产生过的冗余,而且容器接口操作上,同样相当的便利。

可以先看个简单使用哈希的例子:

/* 初始化hash, 哈希桶大小8
 * 键:大小写敏感字符串
 * 值:long整型
 */
tb_hash_ref_t hash = tb_hash_init(8, tb_item_func_str(tb_true), tb_item_func_long());
if (hash)
{
    // 设置键值对:"key" => 123
    tb_hash_set(hash, "key", (tb_pointer_t)123);

    // 获取值
    tb_long_t value = (tb_long_t)tb_hash_get(hash, "key");

    // 退出hash
    tb_hash_exit(hash);
}

/* 初始化hash, 哈希桶大小: TB_HASH_BULK_SIZE_MICRO
 * 键:tb_struct_xxxx_t 结构体类型,内存数据由hash内部自己维护, 后面两个参数设置成员的释放回调函数
 * 值:true类型,永远是tb_true, 这种hash相当于stl的set<tb_struct_xxxx_t>,内部会去优化掉value占用的内存
 */
tb_hash_ref_t hash = tb_hash_init(TB_HASH_BULK_SIZE_MICRO, tb_item_func_mem(sizeof(tb_struct_xxxx_t), tb_null, tb_null), tb_item_func_true());
if (hash)
{
    // 初始化tb_struct_xxxx_t
    tb_struct_xxxx_t xxxx = {0};

    // 设置键值对:xxxx => tb_true
    tb_hash_set(hash, &xxxx, (tb_pointer_t)tb_true);

    // 判断键是否存在
    if (tb_hash_get(hash, &xxxx)) 
    {
        // ...
    }

    // 退出hash
    tb_hash_exit(hash);
}

/* 初始化hash, 哈希桶大小使用默认大小: 0
 * 键:大小写不敏感字符串
 * 值:uint8整型
 */
tb_hash_ref_t hash = tb_hash_init(0, tb_item_func_str(tb_false), tb_item_func_uint8());
if (hash)
{
    // 设置键值对:"key" => 123
    tb_hash_set(hash, "key", (tb_pointer_t)123);

    // 获取u位整型键值
    tb_uint8_t value = (tb_uint8_t)tb_hash_get(hash, "key");

    // 退出hash
    tb_hash_exit(hash);
}

怎么样,简单吧。各种类型项都是可以在键值上互用的,而且会去适配tb_hash_get和tb_hash_set等容器接口参数。

你也可以很方便的在初始化容器的时候,自定义成员释放函数、成员比较函数、哈希计算函数等,例如:

// 指针成员释放函数
static tb_void_t tb_hash_item_ptr_free(tb_item_func_t* func, tb_pointer_t buff)
{
    // 断言检测
    tb_assert_and_check_return(func && buff);

    // 获取用户私有数据
    tb_pointer_t priv = func->priv;

    /* 获取成员数据,这里为tb_pointer_t类型,buff是指向成员数据的指针
     *
     * 如果是tb_item_func_str()项类型,数据就是:
     * tb_char_t* data = *((tb_char_t**)buff);
     *    
     * 如果是tb_item_func_mem()项类型,数据就是:
     * tb_byte_t* data = (tb_byte_t*)buff;
     *
     * 因为tb_item_func_mem是吧成员数据的内存都放到了容器里面维护,所以
     * buff指向的就是成员数据本身的地址
     *
     * 而str、ptr只是把指针存到了容器中,所以item指向的是指针的地址,这个需要
     * 注意的,不然很容易出问题
     */
    tb_pointer_t data = *((tb_pointer_t*)buff);
    
    // 释放它
    if (data) tb_free(data);

    // 清空成员数据
    *((tb_pointer_t*)buff) = tb_null;
}

// long 比较函数,改成反序比较
static tb_long_t tb_hash_item_long_comp(tb_item_func_t* func, tb_cpointer_t ldata, tb_cpointer_t rdata)
{
    return ((tb_long_t)ldata < (tb_long_t)rdata? 1 : ((tb_long_t)ldata > (tb_long_t)rdata? -1 : 0));
}

// 初始化long整型比较函数
tb_item_func_t func = tb_item_func_long();

// 替换比较函数, ptr有快捷的传入方式,当然也可以这样传
func.comp = tb_hash_item_long_comp;

// 初始化hash
tb_hash_ref_t hash = tb_hash_init(0, func, tb_item_func_ptr(tb_hash_item_ptr_free, "private data"));

本文转载自:http://tboox.org/cn/2016/02/04/container-hash/

共有 人打赏支持
下一篇: xml解析
ruki

ruki

粉丝 61
博文 103
码字总数 23669
作品 7
松江
高级程序员
私信 提问
并发---ConcurrentHashMap

线程不安全的HashMap 因为多线程环境下,使用HashMap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap,如以下代码 final HashMap<String, String> map = ...

一别经年
2014/01/12
0
0
深入分析ConcurrentHashMap

术语定义 术语 英文 解释 哈希算法 hash algorithm 是一种将任意内容的输入转换成相同长度输出的加密方式,其输出被称为哈希值。 哈希表 hash table 根据设定的哈希函数H(key)和处理冲突方法...

markGao
2014/02/28
0
0
聊聊并发(四)深入分析ConcurrentHashMap

哈希算法:是一种将任意内容的输入转换成相同长度输出的加密方式,其输出被称为哈希值。哈希表:根据设定的哈希函数H(key)和处理冲突方法将一组关键字映象到一个有限的地址区间上,并以关键字...

陶邦仁
2015/03/19
0
1
深入分析ConcurrentHashMap(VS Hashtable VS HashMap)

聊聊并发(四)深入分析ConcurrentHashMap本文是作者原创,发表于InfoQ:http://www.infoq.com/cn/articles/ConcurrentHashMap 术语定义术语 英文 解释哈希算法 hash algorithm 是一种将任意...

tantexian
2016/05/27
27
0
【充电】《Nginx核心知识100讲》nginx 哈希表、红黑树

39 | 哈希表的maxsize与bucketsize如何配置 nginx的容器是很多nginx高级功能的实现基础。即使不需要编写第三方模块、查看nginx源代码。但变更nginx配置文件达到最大化的性能,也需要了解ngi...

言十年
01/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring学习记录

Java类定义配置 @Configuration //标记为配置类@ComponentScan //标记为扫描当前包及子包所有标记为@Component的类@ComponentScan(basePackageClasses = {接口.class,...}) //标记为扫描当...

CHONGCHEN
16分钟前
0
0
如何开发一款以太坊(安卓)钱包系列2 - 导入账号及账号管理

这是如何开发一款以太坊(安卓)钱包系列第2篇,如何导入账号。有时用户可能已经有一个账号,这篇文章接来介绍下,如何实现导入用户已经存在的账号。 导入账号预备知识 从用户需求上来讲,导...

Tiny熊
今天
3
0
intellJ IDEA搭建java+selenium自动化环境(maven,selenium,testng)

1.安装jdk1.8; 2.安装intellJ; 3.安装maven; 3.1 如果是单前用户,配置用户环境变量即可,如果是多用户,则需配置系统环境变量,变量名为MAVEN_HOME,赋值D:\Application\maven,往path中...

不最醉不龟归
今天
4
0
聊聊ShenandoahGC的Brooks Pointers

序 本文主要研究一下ShenandoahGC的Brooks Pointers Shenandoah Shenandoah面向low-pause-time的垃圾收集器,它的GC cycle主要有 Snapshot-at-the-beginning concurrent mark包括Init Mark(P......

go4it
昨天
4
0
Makefile通用编写规则

#简单实用的Makefile模板: objs := a.o b.o test:$(objs) gcc -o test $^ # .a.o.d .b.o.d dep_files := $(foreach f,$(objs),.$(f).d) dep_files := $(wildcard $(dep_files)) ifneq ($(d......

shzwork
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部