[转] HashMap

/********************************************************************
*
*   本文件是FKMMORPG的一部分。
*
*   文件名:    HashMap
*   作者:     FreeKnightDuzhi[ 王宏张 ]
*   文件说明:   哈希表模板类
*
*   修改人:        
*   修改内容:
*********************************************************************/

#pragma once

//==================================================================================================================

namespace FK3DEngine
{
    //--------------------------------------------------------------------------------------------------------------
    //哈希表模板类
    template <typename T> class FK_DLL HashMap
    {
    public:
        //哈希字符串最大长度
        static const int        mMaxHashStrLen = 32;

        //哈希元素结构
        struct HashData
        {
            T               Data;                       //存储数据

            char            szKeyName[mMaxHashStrLen];  //键名
            unsigned short  nKeyNameLen;                //键名长度

            HashData*       pNext;                      //下一个元素的指针
            HashData*       pPrev;                      //上一个元素的指针

            unsigned int    nStackIndex;                //该元素在堆栈中的索引号
        };

    public:
        unsigned int            mnTableSize;    //哈希元素索引表大小
        HashData**              mpHashTable;    //哈希元素索引表

        UINT                    mNumData;       //哈希元素数量
        Stack< HashData* >      mHashDataStack; //哈希元素指针堆栈(用来进行快速轮循)

    public:
        HashMap();
        ~HashMap();

        //初始化哈希表(nTableSize 为哈希表大小,如果添加的元素超过了此数值将造成重复率极高。)
        void Initialize( unsigned int nTableSize );

        //清空哈希表
        void Clear();

        //释放哈希表
        void Release();

        //加入元素
        bool Add( const T& refData, const char* szKeyName );

        //删除元素
        void Del( const char* szKeyName );

        //寻找元素
        T* Find( const char* szKeyName );

        //返回当前元素数
        FKInline unsigned int Size() const;
    };
    //--------------------------------------------------------------------------------------------------------------
}
/********************************************************************
*
*   本文件是FKMMORPG的一部分。本文件版权归属FreeKnightDuzhi(王宏张)所有。
*
*   文件名:    HashMap
*   作者:     FreeKnightDuzhi[ 王宏张 ]
*   文件说明:   
*
*   修改人:        
*   修改内容:
*********************************************************************/

#pragma once

//==================================================================================================================

#ifndef FK_NO_TEMPLATE_IMPLEMNTATION

//==================================================================================================================

namespace FK3DEngine
{
    //--------------------------------------------------------------------------------------------------------------
    template <typename T> HashMap<T>::HashMap()
        : mnTableSize   (0)
        , mpHashTable   (NULL)
        , mNumData      (0)
    {
    }
    //--------------------------------------------------------------------------------------------------------------
    template <typename T> HashMap<T>::~HashMap()
    {
        Release();
    }
    //--------------------------------------------------------------------------------------------------------------
    //初始化哈希表(nTableSize 为哈希表大小,如果添加的元素超过了此数值将造成重复率极高。)
    template <typename T> void HashMap<T>::Initialize( unsigned int nTableSize )
    {
        //初始化堆栈
        mHashDataStack.Initialize( nTableSize, nTableSize >> 2 );

        //初始化哈希元素索引表内存
        mnTableSize = nTableSize;

        size_t nTableLen = sizeof(HashData*) * nTableSize;
        mpHashTable = (HashData**)malloc( nTableLen );
        if( mpHashTable == NULL )
        {
            Misc::ShowErrMsg( "初始化哈希表(%s)内存失败。", __FUNCSIG__ );
            return;
        }

        memset( mpHashTable, 0, nTableLen );
    }
    //--------------------------------------------------------------------------------------------------------------
    //清空哈希表
    template <typename T> void HashMap<T>::Clear()
    {
        //释放所有哈希元素
        unsigned int nStackSize = mHashDataStack.Size();
        HashData** ppHashData = mHashDataStack.Begin();
        for( unsigned int i=0; i<nStackSize; ++i )
        {
            SafeFree( *ppHashData );
            ++ppHashData;
        }

        mHashDataStack.Clear();
        memset( mpHashTable, 0, sizeof(HashData*) * mnTableSize );
    }
    //--------------------------------------------------------------------------------------------------------------
    //释放哈希表
    template <typename T> void HashMap<T>::Release()
    {
        //释放所有哈希元素
        unsigned int nStackSize = mHashDataStack.Size();
        HashData** ppHashData = mHashDataStack.Begin();
        for( unsigned int i=0; i<nStackSize; ++i )
        {
            if( *ppHashData != NULL )
                free( *ppHashData );

            ppHashData++;
        }

        mHashDataStack.Release();
        SafeFree( mpHashTable );
    }
    //--------------------------------------------------------------------------------------------------------------
    //加入元素
    template <typename T> bool HashMap<T>::Add( const T& refData, const char* szKeyName )
    {
        //计算键名哈希值作为该元素在索引表中的位置
        size_t nStrLen = 0;
        unsigned int nPos = Misc::HashString( szKeyName, &nStrLen ) % mnTableSize;

        //检查键名字符串长度
        if( nStrLen >= 32 )
        {
            Misc::ShowErrMsg( "哈希表(%s)键名不允许超过 %d 个字符。", __FUNCSIG__, mMaxHashStrLen );
            return false;
        }

        //创建新的哈希元素
        HashData* pHashData = (HashData*)malloc( sizeof(HashData) );
        if( pHashData == NULL )
        {
            Misc::ShowErrMsg( "分配哈希表(%s)内存失败。", __FUNCSIG__ );
            return false;
        }

        //复制元素数据
        pHashData->nKeyNameLen = (unsigned short)nStrLen;
        memcpy( pHashData->szKeyName, szKeyName, nStrLen + 1 );

        pHashData->Data = refData;
        pHashData->pPrev = NULL;
        pHashData->pNext = NULL;
        pHashData->nStackIndex = mHashDataStack.Size();

        //如果该位置已经存在哈希元素
        if( mpHashTable[nPos] != NULL )
        {
            HashData* pExistData = mpHashTable[nPos];

CheckNextKey:
            //如果键名长度相同
            if( pExistData->nKeyNameLen == (unsigned short)nStrLen )
            {
                //且键名相同
                if( 0 == memcmp( pExistData->szKeyName, szKeyName, nStrLen ) )
                {
                    return false;
                }
            }

            if( pExistData->pNext != NULL )
            {
                pExistData = pExistData->pNext;
                goto CheckNextKey;
            }

            pExistData->pNext = pHashData;
            pHashData->pPrev = pExistData;
        }
        //如果该位置为空
        else
        {
            mpHashTable[nPos] = pHashData;
        }

        //将此元素指针加入堆栈索引表
        *mHashDataStack.Push() = pHashData;

        ++mNumData;

        return true;
    }
    //--------------------------------------------------------------------------------------------------------------
    //删除元素
    template <typename T> void HashMap<T>::Del( const char* szKeyName )
    {
        //计算键名哈希值作为该元素在索引表中的位置
        size_t nStrLen = 0;
        unsigned int nPos = Misc::HashString( szKeyName, &nStrLen ) % mnTableSize;

        //检查键名字符串长度
        if( nStrLen >= 32 )
        {
            Misc::ShowErrMsg( "哈希表(%s)键名不允许超过 %d 个字符。", __FUNCSIG__, mMaxHashStrLen );
            return;
        }

        //如果在哈希表中找不到该元素
        if( mpHashTable[nPos] == NULL )
        {
            Misc::ShowErrMsg( "在哈希表(%s)中找不到键名为 '%s' 的元素。", __FUNCSIG__, szKeyName );
            return;
        }

        //如果找到
        HashData* pHashData = mpHashTable[nPos];

        //如果该位置不只有一个元素
        if( pHashData->pNext != NULL )
        {
CheckNextKey:
            //如果键名长度相同
            if( pHashData->nKeyNameLen == (unsigned short)nStrLen )
            {
                //且键名相同
                if( 0 == memcmp( pHashData->szKeyName, szKeyName, nStrLen ) )
                    goto FoundKey;
            }

            //如果该位置没有其它元素了
            if( pHashData->pNext == NULL )
            {
                Misc::ShowErrMsg( "在哈希表(%s)中找不到键名为 '%s' 的元素。", __FUNCSIG__, szKeyName );
                return;
            }
            //否则继续查询下一个键
            else
            {
                pHashData = pHashData->pNext;
                goto CheckNextKey;
            }
        }

FoundKey:
        //如果该元素之前存在其它元素
        if( pHashData->pPrev != NULL )
        {
            HashData* pParent = pHashData->pPrev;

            //如果在其之后也有元素则将它的前一个元素和它的后一个元素连接起来
            if( pHashData->pNext != NULL )
            {
                pParent->pNext = pHashData->pNext;
                pHashData->pNext->pPrev = pParent;
            }
            //否则只清空它的前面的元素指向该元素的指针
            else
            {
                pParent->pNext = NULL;
            }
        }
        //如果该元素之前没有其它元素
        else
        {
            //如果在其之后有元素则将之后的元素作为该位置第一个元素
            if( pHashData->pNext != NULL )
            {
                mpHashTable[nPos] = pHashData->pNext;
                mpHashTable[nPos]->pPrev = NULL;
            }
            //如果在其之后没有元素则将该位置清空
            else
                mpHashTable[nPos] = NULL;
        }

        //清空该哈希元素在索引堆栈中的指针
        *( mHashDataStack.Begin() + pHashData->nStackIndex ) = NULL;

        //释放该哈希元素内存
        free( pHashData );

        --mNumData;
    }
    //--------------------------------------------------------------------------------------------------------------
    //寻找元素
    template <typename T> T* HashMap<T>::Find( const char* szKeyName )
    {
        //计算键名哈希值作为该元素在索引表中的位置
        size_t nStrLen = 0;
        int nPos = Misc::HashString( szKeyName, &nStrLen ) % mnTableSize;

        //检查键名字符串长度
        if( nStrLen >= 32 )
        {
            Misc::ShowErrMsg( "哈希表(%s)键名不允许超过 %d 个字符。", __FUNCSIG__, mMaxHashStrLen );
            return NULL;
        }

        //如果在哈希表中找不到该元素
        if( mpHashTable[nPos] == NULL )
        {
            Misc::ShowErrMsg( "在哈希表(%s)中找不到键名为 '%s' 的元素。", __FUNCSIG__, szKeyName );
            return NULL;
        }

        //如果找到
        HashData* pHashData = mpHashTable[nPos];

        //如果该位置不只有一个元素
        if( pHashData->pNext != NULL )
        {
CheckNextKey:
            //如果键名长度相同
            if( pHashData->nKeyNameLen == (unsigned short)nStrLen )
            {
                //且键名相同
                if( 0 == memcmp( pHashData->szKeyName, szKeyName, nStrLen ) )
                {
                    goto FoundKey;
                }
            }

            //如果该位置没有其它元素了
            if( pHashData->pNext == NULL )
            {
                Misc::ShowErrMsg( "在哈希表(%s)中找不到键名为 '%s' 的元素。", __FUNCSIG__, szKeyName );
                return NULL;
            }
            //否则继续查询下一个键
            else
            {
                pHashData = pHashData->pNext;
                goto CheckNextKey;
            }
        }

FoundKey:
        return &pHashData->Data;
    }

    //返回当前元素数
    template <typename T> FKInline unsigned int HashMap<T>::Size() const
    {
        return mNumData;
    }
}
#endif  /* #ifndef FK_NO_TEMPLATE_IMPLEMNTATION */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java对象HashMap可以使用阿里的fastjson工具或者hutool工具类来实现。 使用fastjson工具,可以通过将Java对象换为JSON字符串,再将JSON字符串换为HashMap。可以使用以下代码实现: ```java import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; public static HashMap<String, Object> objectToMap(Object object) { String jsonString = JSON.toJSONString(object); JSONObject jsonObject = JSON.parseObject(jsonString); return jsonObject.toJavaObject(HashMap.class); } ``` 使用hutool工具类,可以直接将Java对象换为JSON对象,再将JSON对象换为HashMap。可以使用以下代码实现: ```java import cn.hutool.json.JSONObject; public static HashMap<String, Object> objectToMap(Object object) { JSONObject jsonObject = new JSONObject(object); return jsonObject.toBean(HashMap.class); } ``` 以上两种方法都可以将Java对象换为HashMap,方便进行后续的操作和处理。 #### 引用[.reference_title] - *1* *3* [JAVA 实体类Entity 对象Object HashMap Xml 互相换](https://blog.csdn.net/fendouweiqian/article/details/121105364)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [java Object对象HashMap](https://blog.csdn.net/a704397849/article/details/102664217)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值