C# 和 Java 中的 HashMap 相当于什么?

438

从Java转到C#,是否有HashMap的等效物?如果没有,你会推荐什么?

7个回答

654

Dictionary 可能是最接近的。 System.Collections.Generic.Dictionary 实现了 System.Collections.Generic.IDictionary 接口(类似于 Java 的 Map 接口)。

你应该注意到一些显著的区别:

  • 添加/获取元素
    • Java的HashMap有putget方法,用于设置/获取元素
      • myMap.put(key, value)
      • MyObject value = myMap.get(key)
    • C#的Dictionary使用[]索引来设置/获取元素
      • myDictionary[key] = value
      • MyObject value = myDictionary[key]
  • null
    • Java的HashMap允许使用null键
    • .NET的Dictionary如果尝试添加null键,则会抛出ArgumentNullException
  • 添加重复键
    • Java的HashMap将使用新值替换现有值。
    • .NET的Dictionary如果使用[]索引,则将使用新值替换现有值。 如果使用Add方法,则会抛出ArgumentException
  • 尝试获取不存在的键
    • Java的HashMap将返回null。
    • .NET的Dictionary将抛出KeyNotFoundException。 您可以使用TryGetValue方法而不是[]索引来避免这种情况:
      MyObject value = null; if (!myDictionary.TryGetValue(key, out value)) { /* key doesn't exist */ }

Dictionary有一个ContainsKey方法,可以帮助处理前两个问题。


9
在Java中,HashMap允许空值和空键,这一点没有完全等价的对应物。请参考http://download.oracle.com/javase/1.4.2/docs/api/java/util/HashMap.html。 - Fabio Maulo
5
是的,词典接近但并不完全准确。 - Powerlord
21
注意,当添加重复的键时,Dictionary 会抛出异常。 - Rubens Mariuzzo
5
当使用一个不存在的键请求值时,会抛出一个异常。 - Rubens Mariuzzo
3
请注意,如果 TryGetValue 返回 false,则它还会将 value 设置为其类型的默认值(通常为0或null,类似于 HashMap 返回的内容)。因此,如果您对此感到满意,在某些情况下甚至不需要检查 TryGetValue 的布尔结果。 - Wizou
显示剩余2条评论

39

来自C#对应Java HashMap的代码

我需要一个接受"null"键的字典,但似乎没有内置的方法,所以我自己编写了一个。实际上很简单。我继承了Dictionary,添加了一个私有字段来保存"null"键的值,然后重写了索引器。代码如下:

public class NullableDictionnary : Dictionary<string, string>
{
    string null_value;

    public StringDictionary this[string key]
    {
        get
        {
            if (key == null) 
            {
                return null_value;
            }
            return base[key];
        }
        set
        {
            if (key == null)
            {
                null_value = value;
            }
            else 
            {
                base[key] = value;
            }
        }
    }
}

希望这对未来的某个人有所帮助。

==========

我将其修改为这种格式。

public class NullableDictionnary : Dictionary<string, object>

7
你能否继续使用泛型主题,将对象作为类型参数? - colithium
这个不行。public StringDictionary this[string key] {... 应该改成 public String this[string key] {...此外,根据我的尝试,base[key] 也不会工作。我建议实现IDictionary接口,只需拥有一个全局私有的字典对象,并处理每个方法的空值情况。 - A.sharif
8
我想知道你为什么特意拼错了“Dictionary”这个单词。 - Jim Balter
12
@JimBalter 很明显他需要一本字典。 - Phillip Elm

33

让我用“codaddict算法”的例子来帮助你理解它。

C#中的'Dictionary'在平行宇宙中是Java中的'Hashmap'。

某些实现是不同的。请参阅下面的示例以更好地理解。

声明Java HashMap:

Map<Integer, Integer> pairs = new HashMap<Integer, Integer>();

声明 C# 字典:

Dictionary<int, int> Pairs = new Dictionary<int, int>();

从一个位置获取值:

pairs.get(input[i]); // in Java
Pairs[input[i]];     // in C#

设置某个位置的值:

pairs.put(k - input[i], input[i]); // in Java
Pairs[k - input[i]] = input[i];    // in C#

以下是Codaddict算法的总体示例。

Java版的codaddict算法:

import java.util.HashMap;

public class ArrayPairSum {

    public static void printSumPairs(int[] input, int k)
    {
        Map<Integer, Integer> pairs = new HashMap<Integer, Integer>();

        for (int i = 0; i < input.length; i++)
        {
            if (pairs.containsKey(input[i]))
                System.out.println(input[i] + ", " + pairs.get(input[i]));
            else
                pairs.put(k - input[i], input[i]);
        }

    }

    public static void main(String[] args)
    {
        int[] a = { 2, 45, 7, 3, 5, 1, 8, 9 };
        printSumPairs(a, 10);

    }
}

Codaddict 在 C# 中的算法

using System;
using System.Collections.Generic;

class Program
{
    static void checkPairs(int[] input, int k)
    {
        Dictionary<int, int> Pairs = new Dictionary<int, int>();

        for (int i = 0; i < input.Length; i++)
        {
            if (Pairs.ContainsKey(input[i]))
            {
                Console.WriteLine(input[i] + ", " + Pairs[input[i]]);
            }
            else
            {
                Pairs[k - input[i]] = input[i];
            }
        }
    }
    static void Main(string[] args)
    {
        int[] a = { 2, 45, 7, 3, 5, 1, 8, 9 };
        //method : codaddict's algorithm : O(n)
        checkPairs(a, 10);
        Console.Read();
    }
}

4
C#9.0 注释:如果您知道变量的类型,可以使用 new(),而不是像之前需要输入 new Dictionary<int, int>()。 :)(尽管这个答案发布时 C#9.0 还未推出,但建议使用本方法编写更易读的代码) - dimitar.bogdanov

8

使用字典 - 它使用哈希表,但是类型安全。

此外,您的Java代码为

int a = map.get(key);
//continue with your logic

这段内容的最佳编码方式是使用C#,代码如下:
int a;
if(dict.TryGetValue(key, out a)){
//continue with your logic
}

通过这种方式,您可以在块内限定变量"a"的作用范围,如果以后需要,它仍然可以在块外部访问。


3
自 C# 7.0 起,可以使用 dict.TryGetValue(key, out int a) 方法。 - nevvermind

6

请查看MSDN上关于Hashtable类的文档。

Hashtable类表示一个基于键的哈希代码组织的键值对集合。

另外,请注意这个类不是线程安全的。


24
Dictionary<TKey, TValue> 更好,因为它在编译时进行类型检查,并且不需要对值类型进行装箱。 - Thorarin

0

我只是想提供我的意见。
这是根据@Powerlord的答案。

"null"放在null字符串中。

private static Dictionary<string, string> map = new Dictionary<string, string>();

public static void put(string key, string value)
{
    if (value == null) value = "null";
    map[key] = value;
}

public static string get(string key, string defaultValue)
{
    try
    {
        return map[key];
    }
    catch (KeyNotFoundException e)
    {
        return defaultValue;
    }
}

public static string get(string key)
{
    return get(key, "null");
}

0

答案是

字典

看一下我的函数,它很简单,使用了字典中最重要的成员函数add。

如果列表包含重复项,则此函数返回false。

 public static bool HasDuplicates<T>(IList<T> items)
    {
        Dictionary<T, bool> mp = new Dictionary<T, bool>();
        for (int i = 0; i < items.Count; i++)
        {
            if (mp.ContainsKey(items[i]))
            {
                return true; // has duplicates
            }
            mp.Add(items[i], true);
        }
        return false; // no duplicates
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接