434

Coming from a Java world into a C# one is there a HashMap equivalent? If not what would you recommend?

Thorarin
  • 47,289
  • 11
  • 75
  • 111
John
  • 4,637
  • 3
  • 21
  • 14

7 Answers7

652

Dictionary is probably the closest. System.Collections.Generic.Dictionary implements the System.Collections.Generic.IDictionary interface (which is similar to Java's Map interface).

Some notable differences that you should be aware of:

  • Adding/Getting items
    • Java's HashMap has the put and get methods for setting/getting items
      • myMap.put(key, value)
      • MyObject value = myMap.get(key)
    • C#'s Dictionary uses [] indexing for setting/getting items
      • myDictionary[key] = value
      • MyObject value = myDictionary[key]
  • null keys
    • Java's HashMap allows null keys
    • .NET's Dictionary throws an ArgumentNullException if you try to add a null key
  • Adding a duplicate key
    • Java's HashMap will replace the existing value with the new one.
    • .NET's Dictionary will replace the existing value with the new one if you use [] indexing. If you use the Add method, it will instead throw an ArgumentException.
  • Attempting to get a non-existent key
    • Java's HashMap will return null.
    • .NET's Dictionary will throw a KeyNotFoundException. You can use the TryGetValue method instead of the [] indexing to avoid this:
      MyObject value = null; if (!myDictionary.TryGetValue(key, out value)) { /* key doesn't exist */ }

Dictionary's has a ContainsKey method that can help deal with the previous two problems.

Powerlord
  • 87,612
  • 17
  • 125
  • 175
  • 9
    There isn't an exact equivalent (in JAVA HashMap permits null values and the null key) http://download.oracle.com/javase/1.4.2/docs/api/java/util/HashMap.html – Fabio Maulo Dec 25 '10 at 18:55
  • 5
    Yes, Dictionary is close but not exact. – Powerlord Dec 25 '10 at 21:00
  • 20
    Note, `Dictionary` throws Exceptions when adding a duplicated key. – Rubens Mariuzzo Dec 27 '11 at 20:08
  • 5
    Also, an Exception is thrown when requesting a value with a non existing key. – Rubens Mariuzzo Dec 27 '11 at 20:20
  • `if (!myDictionary.TryGetValue(key, value))` needs an `out` for the second argument. So `if (!myDictionary.TryGetValue(key, out value))` – bugybunny Oct 18 '18 at 10:12
  • @bugybunny Good catch. This is why you should always test code when putting it into answers... and I clearly didn't. – Powerlord Oct 18 '18 at 19:17
  • 3
    Note that if `TryGetValue` returns false, it **also** sets `value` to `default` for its type (typically 0 or null, which would be similar to what `HashMap` returns). So if you're happy with that, in some case you don't even need to check the boolean result of `TryGetValue` – Wizou Jul 25 '19 at 10:41
39

From C# equivalent to Java HashMap

I needed a Dictionary which accepted a "null" key, but there seems to be no native one, so I have written my own. It's very simple, actually. I inherited from Dictionary, added a private field to hold the value for the "null" key, then overwritten the indexer. It goes like this :

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;
            }
        }
    }
}

Hope this helps someone in the future.

==========

I modified it to this format

public class NullableDictionnary : Dictionary<string, object>
Kurru
  • 14,180
  • 18
  • 64
  • 84
KeithC
  • 447
  • 4
  • 3
  • 7
    Couldn't you continue the generics theme by making object a type parameter? – colithium Jan 28 '12 at 03:44
  • This doesn't work. public StringDictionary this[string key] {... should be public String this[string key] {. Also base[key] won't work from my try. I suggest implementing IDictionary and just having a global private dictionary object and handling the null case for each of the methods. – A.sharif May 15 '15 at 21:40
  • 8
    I wonder why you went out of your way to misspell Dictionary. – Jim Balter Jul 22 '15 at 17:53
  • 12
    @JimBalter Clearly he needs a dictionary. – Phillip Elm Feb 05 '17 at 23:32
32

Let me help you understand it with an example of "codaddict's algorithm"

'Dictionary in C#' is 'Hashmap in Java' in parallel universe.

Some implementations are different. See the example below to understand better.

Declaring Java HashMap:

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

Declaring C# Dictionary:

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

Getting a value from a location:

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

Setting a value at location:

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

An Overall Example can be observed from below Codaddict's algorithm.

codaddict's algorithm in Java:

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's algorithm in 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();
    }
}
Ajay Yadiki
  • 507
  • 5
  • 7
  • 4
    C#9.0 comment: you can use `new()` if you know the type of a variable, instead of typing out `new Dictionary()` for example. :) (this answer was posted way before C#9.0 but readers using this code are advised to write more readable code) – dimitar.bogdanov Apr 27 '21 at 07:34
8

Use Dictionary - it uses hashtable but is typesafe.

Also, your Java code for

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

will be best coded in C# this way:

int a;
if(dict.TryGetValue(key, out a)){
//continue with your logic
}

This way, you can scope the need of variable "a" inside a block and it is still accessible outside the block if you need it later.

Shree Harsha
  • 377
  • 3
  • 9
6

Check out the documentation on MSDN for the Hashtable class.

Represents a collection of key-and-value pairs that are organized based on the hash code of the key.

Also, keep in mind that this is not thread-safe.

jamesmortensen
  • 33,636
  • 11
  • 99
  • 120
Ray
  • 1,585
  • 9
  • 10
  • 24
    `Dictionary` is preferable, because of compile time type checking and because it doesn't require boxing of value types. – Thorarin Aug 13 '09 at 16:56
0

the answer is

Dictionary

take look at my function, its simple add uses most important member functions inside Dictionary

this function return false if the list contain Duplicates items

 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
    }
Basheer AL-MOMANI
  • 14,473
  • 9
  • 96
  • 92
0

I just wanted to give my two cents.
This is according to @Powerlord 's answer.

Puts "null" instead of null strings.

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");
}
ossobuko
  • 851
  • 8
  • 25