5.Hashtable

5.简单数据结构类-Hashtable


5.1 知识点

Hashtable的本质

Hashtable(又称散列表)是基于键的哈希代码组织起来的键/值对,其主要作用是提高数据查询的效率。使用键来访问集合中的元素。

Hashtable的申明

需要引用命名空间 System.Collections

Hashtable hashtable = new Hashtable();

Hashtable的增删查改和遍历

当前hashtable中的元素有:

{}

Add方法:传入键和值。

hashtable.Add(1, "123");
hashtable.Add("123", 2);
hashtable.Add(true, false);
hashtable.Add(false, false);
// 注意:不能出现相同键
// hashtable.Add(1, "123");// 报错,不能出现相同键

增完之后hashtable中的元素有:

{
    键:123 值:2
    键:False 值:False
    键:1 值:"123"
    键:True 值:False
}

当前hashtable中的元素有:

{
    键:123 值:2
    键:False 值:False
    键:1 值:"123"
    键:True 值:False
}

Remove方法:传入键,只能通过键去删除。

hashtable.Remove(1);
// 要是删除不存在的键的话,没有反应
hashtable.Remove(2);

Clear方法:直接清空。

// hashtable.Clear(); // 会清空哈希表,为后面方便演示,注释

删完之后hashtable中的元素有:

{
    键:123 值:2
    键:False 值:False
    键:True 值:False
}

当前hashtable中的元素有:

{
    键:123 值:2
    键:False 值:False
    键:True 值:False
}

Hashtable[key]索引器get:通过键查看值。

Console.WriteLine(hashtable["123"]); // 2
// 找不到会返回空
Console.WriteLine(hashtable[4]); // null
Console.WriteLine(hashtable["123123"]); // null

Contains方法ContainsKey方法:传入键,查看键是否存在于哈希表中。存在返回true,否则返回false

// 根据键检测
if (hashtable.Contains("123"))
{
    Console.WriteLine("存在键为123的键值对"); // 存在键为123的键值对
}
if (hashtable.ContainsKey(2))
{
    Console.WriteLine("存在键为2的键值对");
}

ContainsValue方法:传入值,查看值是否存在于哈希表中。存在返回true,否则返回false

// 根据值检测
if (hashtable.ContainsValue(2))
{
    Console.WriteLine("存在值为2的键值对"); // 存在值为2的键值对
}

当前hashtable中的元素有:

{
    键:123 值:2
    键:False 值:False
    键:True 值:False
}

Hashtable[key]索引器set:通过键修改值。

// 只能改变键对应的值内容,无法修改键
Console.WriteLine(hashtable[false]); // False 传键时不能输入大写False,输入小写的false
hashtable[false] = 100.5f;
Console.WriteLine(hashtable[false]); // 100.5f

改完之后hashtable中的元素有:

{
    键:123 值:2
    键:False 值:100.5f
    键:True 值:False
}

遍历

当前hashtable中的元素有:

{
    键:123 值:2
    键:False 值:100.5f
    键:True 值:False
}

Count属性:返回键值对数量。

Console.WriteLine(hashtable.Count); // 3

foreach遍历所有键Hashtable.Keys得到所有键。

foreach (object item in hashtable.Keys)
{
    Console.WriteLine("键:" + item);
    Console.WriteLine("值:" + hashtable[item]);
    // 打印如下,无序
    //{
    //    键:123 值:2
    //    键:False 值:100.5f
    //    键:True 值:False
    //}
}

foreach遍历所有值Hashtable.Values得到所有值。

foreach (object item in hashtable.Values)
{
    Console.WriteLine("值:" + item);
    // 打印如下,无序
    //{
    //    值:2
    //    值:100.5f
    //    值:False
    //}
}

foreach遍历键值对

// DictionaryEntry和迭代器相关,是一个数据结构,里面存了一个键和一个值
// item.Key得到当前键,item.Value得到当前值
foreach (DictionaryEntry item in hashtable)
{
    Console.WriteLine("键:" + item.Key + " 值:" + item.Value);
    // 打印如下,无序
    //{
    //    键:123 值:2
    //    键:False 值:100.5f
    //    键:True 值:False
    //}
}

迭代器遍历法

通过HashtableGetEnumerator方法获得一个IDictionaryEnumerator字典枚举器接口对象。IDictionaryEnumerator字典枚举器接口有KeyValue

IDictionaryEnumerator myEnumerator = hashtable.GetEnumerator();
// IDictionaryEnumerator接口里的MoveNext方法相当于一个游标,只要后面还有键值对会返回true
bool flag = myEnumerator.MoveNext();
// while循环遍历哈希表
while (flag)
{
    // 打印IDictionaryEnumerator字典枚举器接口的Key和Value
    Console.WriteLine("IDictionaryEnumerator 键:" + myEnumerator.Key + " IDictionaryEnumerator 值:" + myEnumerator.Value);
    // 通过MoveNext方法判断后面还有没有键值对
    flag = myEnumerator.MoveNext();

    // 打印如下,无序
    //{
    //    IDictionaryEnumerator 键:True IDictionaryEnumerator 值:False
    //    IDictionaryEnumerator 键:False IDictionaryEnumerator 值:100.5
    //    IDictionaryEnumerator 键:123 IDictionaryEnumerator 值:2
    //}
}

Hashtable的装箱拆箱

由于用object来存储数据,自然存在装箱拆箱。当往其中进行值类型存储时就是在装箱,当将值类型对象取出来转换使用时,就存在拆箱。


5.2 知识点代码

using System;
using System.Collections;

namespace Lesson4_Hashtable
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hashtable");

            #region 知识点一 Hashtalbe的本质
            //Hashtable(又称散列表) 是基于键的哈希代码组织起来的 键/值对
            //它的主要作用是提高数据查询的效率
            //使用键来访问集合中的元素
            #endregion

            #region 知识点二 Hashtalbe的申明
            //需要引用命名空间 System.Collections
            Hashtable hashtable = new Hashtable();
            #endregion

            #region 知识点三 Hashtalbe的增删查改和遍历

            #region 增

            //当前hashtable中的元素有
            //{}

            //Add方法 传入键和值
            hashtable.Add(1, "123");
            hashtable.Add("123", 2);
            hashtable.Add(true, false);
            hashtable.Add(false, false);
            //注意:不能出现相同键
            //hashtable.Add(1, "123");//报错 不能出现相同键

            //增完之后hashtable中的元素有
            //{
            //键:123 值:2
            //键:False 值:False
            //键:1 值:123
            //键:True 值:False
            //}


            #endregion

            #region 删

            //当前hashtable中的元素有
            //{
            //键:123 值:2
            //键:False 值:False
            //键:1 值:123
            //键:True 值:False
            //}

            //1.Remove方法 传入键 只能通过键去删除
            hashtable.Remove(1);
            //要是删除不存在的键的话 没反应
            hashtable.Remove(2);

            //2.Clear方法 直接清空
            //hashtable.Clear();//会清空哈希表 为后面方便演示 注释

            //删完之后hashtable中的元素有
            //{
            //键:123 值:2
            //键:False 值:False
            //键:True 值:False
            //}

            #endregion

            #region 查

            //当前hashtable中的元素有
            //{
            //键:123 值:2
            //键:False 值:False
            //键:True 值:False
            //}

            //Hashtable[key] 通过键查看值
            Console.WriteLine(hashtable["123"]);//2
            //找不到会返回空
            Console.WriteLine(hashtable[4]);//null
            Console.WriteLine(hashtable["123123"]);//null

            //Contains方法 ContainsKeys方法 传入键 查看键是否存在于哈希表中 存在返回true 否则返回false
            //根据键检测
            if (hashtable.Contains("123"))
            {
                Console.WriteLine("存在键为123的键值对");//存在键为123的键值对
            }
            if (hashtable.ContainsKey(2))
            {
                Console.WriteLine("存在键为2的键值对");
            }

            //ContainsValue方法 传入值 查看值是否存在于哈希表中 存在返回true 否则返回false
            //根据值检测
            if (hashtable.ContainsValue(2))
            {
                Console.WriteLine("存在值为2的键值对");//存在值为2的键值对
            }

            #endregion

            #region 改

            //当前hashtable中的元素有
            //{
            //键:123 值:2
            //键:False 值:False
            //键:True 值:False
            //}

            //Hashtable[key] 通过键修改值
            //只能改 键对应的值内容 无法修改键
            Console.WriteLine(hashtable[false]);//False 传键时不能输入大写False 输入小写的false
            hashtable[false] = 100.5f;
            Console.WriteLine(hashtable[false]);//100.5f

            //改完之后hashtable中的元素有
            //{
            //键:123 值:2
            //键:False 值:100.5f
            //键:True 值:False
            //}

            #endregion

            #region 遍历

            //当前hashtable中的元素有
            //{
            //键:123 值:2
            //键:False 值:100.5f
            //键:True 值:False
            //}

            //Count属性 返回键值对 对数
            Console.WriteLine(hashtable.Count);//3

            //foreach遍历所有键 Hashtable.Keys得到所有键
            foreach (object item in hashtable.Keys)
            {
                Console.WriteLine("键:" + item);
                Console.WriteLine("值:" + hashtable[item]);
                //打印如下 无序
                //{
                //键:123 值:2
                //键:False 值:100.5f
                //键:True 值:False
                //}
            }

            //foreach遍历所有值 Hashtable.Values得到所有值
            foreach (object item in hashtable.Values)
            {
                Console.WriteLine("值:" + item);
                //打印如下 无序
                //{
                //值:2
                //值:100.5f
                //值:False
                //}
            }

            //foreach遍历键值对
            //DictionaryEntry和迭代器相关 是一个数据结构 里面存了一个键一个值
            //item.Key得到当前键 item.Value得到当前值
            foreach (DictionaryEntry item in hashtable)
            {
                Console.WriteLine("键:" + item.Key + "值:" + item.Value);
                //打印如下 无序
                //{
                //键:123 值:2
                //键:False 值:100.5f
                //键:True 值:False
                //}
            }

            //迭代器遍历法
            //通过Hashtable的GetEnumerator方法获得一个IDictionaryEnumerator字典枚举器接口对象
            //IDictionaryEnumerator字典枚举器接口有Key和Value
            IDictionaryEnumerator myEnumerator = hashtable.GetEnumerator();
            //IDictionaryEnumerator接口里的MoveNext方法相当于一个游标 只要后面还有键值对会返回true
            bool flag = myEnumerator.MoveNext();
            //while循环遍历哈希表
            while (flag)
            {
                //打印IDictionaryEnumerator字典枚举器接口的Key和Value
                Console.WriteLine("IDictionaryEnumerator键:" + myEnumerator.Key + "IDictionaryEnumerator值:" + myEnumerator.Value);
                //通过MoveNext方法判断后面还有没有键值对
                flag = myEnumerator.MoveNext();

                //打印如下 无序
                //{
                //IDictionaryEnumerator键:TrueIDictionaryEnumerator值:False
                //IDictionaryEnumerator键:FalseIDictionaryEnumerator值:100.5
                //IDictionaryEnumerator键:123IDictionaryEnumerator值:2
                //}
            }

            #endregion

            #endregion

            #region 知识点四 Hashtable的装箱拆箱
            //由于用万物之父来存储数据,自然存在装箱拆箱
            //当往其中进行值类型存储时就是在装箱
            //当将值类型对象取出来转换使用时,就存在拆箱
            #endregion
        }
    }
}

5.3 练习题

请描述Hashtable的存储规则

  • Hashtable是一种键值对形式存储的容器。
  • 每个键对应一个值,其中键和值的类型都是object
  • Hashtable的键是唯一的,即不能重复。

制作一个怪物管理器,提供创建怪物,移除怪物的方法。每个怪物都有自己的唯一ID

class语句块外 namespace语句块内

/// <summary>
/// 怪物管理器类,因为一般管理器都是唯一的,所以把它做成一个单例模式的对象
/// </summary>
class MonsterMgr
{
    // 怪物管理器单例 初始化new出来
    private static MonsterMgr instance = new MonsterMgr();

    // 怪物管理器单例 提供给外部使用 得到唯一的怪物管理器 第一次使用的时候会new出来
    public static MonsterMgr Instance
    {
        get
        {
            return instance;
        }
    }

    // 私有的怪物管理器构造函数 外面new不出来
    private MonsterMgr()
    {

    }

    // 怪物哈希表
    private Hashtable monstersTable = new Hashtable();

    // 怪物id默认是0
    private int monsterID = 0;

    // 添加怪物
    public void AddMonster()
    {
        // 添加怪物时创建怪物
        Monster monster = new Monster(monsterID);
        Console.WriteLine("创建了id为{0}的怪物", monsterID);

        // 怪物id+1
        ++monsterID;

        // 存到怪物哈希表中
        // Hashtable的键是不能重复的,所以一定是用唯一ID
        monstersTable.Add(monster.id, monster);
    }

    // 移除怪物
    public void RemoveMonster(int monsterID)
    {
        // 判断怪物哈希表中有没有这个怪物id
        if (monstersTable.ContainsKey(monsterID))
        {
            // 有的话调用怪物死亡
            (monstersTable[monsterID] as Monster).Dead();

            // 怪物哈希表中移除
            monstersTable.Remove(monsterID);
        }
    }
}

// 怪物类
class Monster
{
    // 怪物唯一id
    public int id;

    // 怪物构造函数 初始化怪物
    public Monster(int id)
    {
        this.id = id;
    }

    // 怪物死亡
    public void Dead()
    {
        Console.WriteLine("怪物{0}死亡", id);
    }
}

主函数内

MonsterMgr.Instance.AddMonster();
MonsterMgr.Instance.AddMonster();
MonsterMgr.Instance.AddMonster();
MonsterMgr.Instance.AddMonster();
MonsterMgr.Instance.AddMonster();
MonsterMgr.Instance.AddMonster();
// 创建了id为0的怪物
// 创建了id为1的怪物
// 创建了id为2的怪物
// 创建了id为3的怪物
// 创建了id为4的怪物
// 创建了id为5的怪物

MonsterMgr.Instance.RemoveMonster(0);
MonsterMgr.Instance.RemoveMonster(3);
// 怪物0死亡
// 怪物3死亡

5.4 练习题代码

using System;
using System.Collections;

namespace Lesson4_练习题
{
    #region 练习题一
    //请描述Hashtable的存储规则

    // 一个键值对形式存储的 容器
    // 一个键 对应一个值
    // 类型是object
    #endregion

    //class语句块外 namespace语句块内

    #region 练习题二
    //制作一个怪物管理器,提供创建怪物
    //移除怪物的方法。每个怪物都有自己的唯一ID


    /// <summary>
    /// 怪物管理器类 因为一般 管理器 都是唯一的 所以把它做成 一个单例模式的对象
    /// </summary>
    class MonsterMgr
    {
        //怪物管理器单例 初始化new出来
        private static MonsterMgr instance = new MonsterMgr();

        //怪物管理器单例 提供给外部使用 得到唯一的怪物管理器 第一次使用的时候会new出来
        public static MonsterMgr Instance
        {
            get
            {
                return instance;
            }
        }

        //私有的怪物管理器构造函数 外面new不出来
        private MonsterMgr()
        {

        }

        //怪物哈希表
        private Hashtable monstersTable = new Hashtable();

        //怪物id默认是0
        private int monsterID = 0;

        //添加怪物
        public void AddMonster()
        {
            //添加怪物时创建怪物
            Monster monster = new Monster(monsterID);
            Console.WriteLine("创建了id为{0}的怪物", monsterID);

            //怪物id+1
            ++monsterID;

            //存到怪物哈希表中
            //Hashtable 的键 是不能重复的 所以一定是用唯一ID
            monstersTable.Add(monster.id, monster);
        }

        //移除怪物
        public void RemoveMonster(int monsterID)
        {
            //判断怪物哈希表中有没有这个怪物id
            if (monstersTable.ContainsKey(monsterID))
            {
                //有的话调用怪物死亡
                (monstersTable[monsterID] as Monster).Dead();

                //怪物哈希表中移除
                monstersTable.Remove(monsterID);
            }
        }
    }

    //怪物类
    class Monster
    {
        //怪物唯一id
        public int id;

        //怪物构造函数 初始化怪物
        public Monster(int id)
        {
            this.id = id;
        }

        //怪物死亡
        public void Dead()
        {
            Console.WriteLine("怪物{0}死亡", id);
        }
    }

    #endregion

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Hashtable练习题");

            //主函数内

            #region 练习题二

            MonsterMgr.Instance.AddMonster();
            MonsterMgr.Instance.AddMonster();
            MonsterMgr.Instance.AddMonster();
            MonsterMgr.Instance.AddMonster();
            MonsterMgr.Instance.AddMonster();
            MonsterMgr.Instance.AddMonster();
            //创建了id为0的怪物
            //创建了id为1的怪物
            //创建了id为2的怪物
            //创建了id为3的怪物
            //创建了id为4的怪物
            //创建了id为5的怪物

            MonsterMgr.Instance.RemoveMonster(0);
            MonsterMgr.Instance.RemoveMonster(3);
            //怪物0死亡
            //怪物3死亡

            #endregion

        }
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏