C# Java HashMap equivalent
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
andget
methods for setting/getting itemsmyMap.put(key, value)
MyObject value = myMap.get(key)
- C#'s Dictionary uses
[]
indexing for setting/getting itemsmyDictionary[key] = value
MyObject value = myDictionary[key]
- Java's HashMap has the
null
keys- Java's
HashMap
allows null keys - .NET's
Dictionary
throws anArgumentNullException
if you try to add a null key
- Java's
- 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 theAdd
method, it will instead throw anArgumentException
.
- Java's
- Attempting to get a non-existent key
- Java's
HashMap
will return null. - .NET's
Dictionary
will throw aKeyNotFoundException
. You can use theTryGetValue
method instead of the[]
indexing to avoid this:MyObject value = null;
if (!myDictionary.TryGetValue(key, out value)) { /* key doesn't exist */ }
- Java's
Dictionary
's has a ContainsKey
method that can help deal with the previous two problems.
How to create a HashMap in C#
Look at Dictionary<key,value>
in the System.Collections.Generic
. It is the C# "parallel" (albeit having some differences, it is the closest to) of HashMap
in Java.
C# Equivalent of Java IdentityHashMap
You can use RuntimeHelpers.GetHashCode(object)
which calls object.GetHashCode()
non-virtually - this is the equivalent of System.identityHashcode
in Java. I think that's what you're after. So your IEqualityComparer
would just use that for hashing and object.ReferenceEquals
for equality.
Java HashMap to a C# Dictionary
FYI: The accepted answer using new
is NOT a port of the provided Java answer. The end result may be the same (and I actually recommend using new instances instead of the methods called player
and attribute
), but it's not a port of the Java answer. I primarily wanted to clarify that in this answer in case someone else comes across this SO question & answer in the future.
Based on the Java code, it seems your program should contain the methods player(String)
and attribute(String, String, String)
, which return a Player
-instance and List<Attribute>
-instance respectively. So you should create those same methods in the C# .NET program.
Your current Java snippet doesn't work as is, and actually would result in a similar error! Try it online.
The accepted answer using the new
to create new instances of the Player
and List<Attribute>
directly may work and give the same results in both programs, but it's not a direct port of your current Java implementation! Otherwise your Java code would have looked like this instead:
Map<Player, List<Attribute>> map = new HashMap<>();
map.put(
new Player("Lebron James"),
new ArrayList<Attribute>(){{
add(new Attribute("mid height"));
add(new Attribute("mid weidght"));
add(new Attribute("high vertical"));
}}
);
Try it online.
Assuming your more complete Java code is something like this:
...
Map<Player, List<Attribute>> map = new HashMap<>();
map.put(
player("Lebron James"),
attribute("mid height", "mid weidght", "high vertical")
);
}
private Player player(String name){
return new Player(name);
}
private List<Attribute> attribute(String... strAttributes){
List<Attribute> resultList = new ArrayList<>();
for(String strAttr : strAttributes){
resultList.add(new Attribute(strAttr));
}
return resultList;
}
Try it online.
The ported C# .NET code would become this:
...
IDictionary<Player, IList<Attribute>> dictionary = new Dictionary<Player, IList<Attribute>>();
dictionary.Add(
player("Lebron James"),
attribute("mid height", "mid weidght", "high vertical")
);
}
private Player player(string name){
return new Player(name);
}
private IList<Attribute> attribute(params string[] strAttributes){
IList<Attribute> resultList = new List<Attribute>();
foreach(string strAttr in strAttributes){
resultList.Add(new Attribute(strAttr));
}
return resultList;
}
Try it online.
Again, I primarily created this answer for other people coming across this question & answer in the future, and to clarify that the accepted answer is not a direct port of the provided Java snippet.
Equivalent Map.Compute in C#
I don't know of an exact equivalent that exists so it may come down to implementing it yourself to some degree. If you're looking for a solution that looks and feels the same, you can add an extension to Dictionary<K,V>
.
There's sufficient differences between these languages to require a bit of hand waiving but, to get to the gist of it, this should suffice as a starting point.
Compute
doesn't exist on the C# Dictionary
so you can add it. Ideally, for an "equivalent", you'd want to ensure it covers all the cases as the original, not just this particular case (IMHO). I don't claim that the following does but you can ensure yours does by investigating the source code for compute
in your Java version. (this is what I came up with looking over HashMap; I could be off).
// You can easily add to the Dictionary<K, V> implementation; SWEET!
public static class DictExtensions
{
public static V Compute<K, V>(this Dictionary<K, V> dict, K key, Func<K, V, V> func)
{
// if no func given, throw.
if (func == null) throw new ArgumentNullException(nameof(func));
// if no mapping, return null.
if (!dict.TryGetValue(key, out var value)) return default;
// get the new value from func.
var result = func(key, value);
if (result == null)
{
// if the mapping exists but func => null,
// remove the mapping and return null.
dict.Remove(key);
return default;
}
// mapping exists and func returned a non-null value.
// set and return the new value
dict[key] = result;
return result;
}
}
Then, after adding a correct using
statement to the code you'd like to use Compute
in, use it like you expect: map.Compute(i, (k, v) => (v == null) ? 1 : v + 1);
Java Map equivalent in C#
You can index Dictionary, you didn't need 'get'.
Dictionary<string,string> example = new Dictionary<string,string>();
...
example.Add("hello","world");
...
Console.Writeline(example["hello"]);
An efficient way to test/get values is TryGetValue
(thanx to Earwicker):
if (otherExample.TryGetValue("key", out value))
{
otherExample["key"] = value + 1;
}
With this method you can fast and exception-less get values (if present).
Resources:
Dictionary-Keys
Try Get Value
Related Topics
Getting All File Names from a Folder Using C#
How to Return Text from Native (C++) Code
ASP.NET Adding Class to Current Menuitem
What Is a Dynamic Language, and Why Doesn't C# Qualify
How to Call (Iron)Python Code from a C# App
How to Post Using Httpclient Content Type = Application/X-Www-Form-Urlencoded
In C#, What Happens When You Call an Extension Method on a Null Object
Unique File Identifier in Windows
Query an Xdocument for Elements by Name at Any Depth
Can a Web User Control (.Ascx) Use a CSS File for Styling
In Ruby, What Is the Equivalent to an Interface in C#
Python: Inflate and Deflate Implementations
How to Tell JSON.Net Globally to Apply the Stringenumconverter to All Enums