Hashmap does not work with int, char

Possible Duplicate:
Storing primitive values in a Java collection?

In java when I use the following :-

public HashMap<char, int> buildMap(String letters)
{
HashMap<char, int> checkSum = new HashMap<char, int>();


for ( int i = 0; i < letters.length(); ++i )
{
checkSum.put(letters.charAt(i), primes[i]);
}


return checkSum;
}

I get errors related to inappropriate types. I solved my problem by using Character and Integer instead of char and int respectively. However, I'm having trouble figuring out why HashMap fails to be able to deal with primitive data types.

172241 次浏览

Generic parameters can only bind to reference types, not primitive types, so you need to use the corresponding wrapper types. Try HashMap<Character, Integer> instead.

However, I'm having trouble figuring out why HashMap fails to be able to deal with primitive data types.

This is due to type erasure. Java didn't have generics from the beginning so a HashMap<Character, Integer> is really a HashMap<Object, Object>. The compiler does a bunch of additional checks and implicit casts to make sure you don't put the wrong type of value in or get the wrong type out, but at runtime there is only one HashMap class and it stores objects.

Other languages "specialize" types so in C++, a vector<bool> is very different from a vector<my_class> internally and they share no common vector<?> super-type. Java defines things though so that a List<T> is a List regardless of what T is for backwards compatibility with pre-generic code. This backwards-compatibility requirement that there has to be a single implementation class for all parameterizations of a generic type prevents the kind of template specialization which would allow generic parameters to bind to primitives.

Hashmaps can only use classes, not primitives. This page from programmerinterview.com might be of use in guiding you to finding the answer. To be honest, I haven't figured out the answer to this problem in detail myself.

Generics can't use primitive types in the form of keywords.

Use

public HashMap<Character, Integer> buildMap(String letters)
{
HashMap<Character, Integer> checkSum = new HashMap<Character, Integer>();


for ( int i = 0; i < letters.length(); ++i )
{
checkSum.put(letters.charAt(i), primes[i]);
}


return checkSum;
}

Updated: With Java 7 and later, you can use the diamond operator.

HashMap<Character, Integer> checkSum = new HashMap<>();

You cannot put primitive types into collections. However, you can declare them using their corresponding object wrappers and still add the primitive values, as long as the boxing allows you.

Generic Collection classes cant be used with primitives. Use the Character and Integer wrapper classes instead.

Map<Character , Integer > checkSum = new HashMap<Character, Integer>();

Generics can be defined using Wrapper classes only. If you don't want to define using Wrapper types, you may use the Raw definition as below

@SuppressWarnings("rawtypes")
public HashMap buildMap(String letters)
{
HashMap checkSum = new HashMap();


for ( int i = 0; i < letters.length(); ++i )
{
checkSum.put(letters.charAt(i), primes[i]);
}
return checkSum;
}

Or define the HashMap using wrapper types, and store the primitive types. The primitive values will be promoted to their wrapper types.

public HashMap<Character, Integer> buildMap(String letters)
{
HashMap<Character, Integer> checkSum = new HashMap<Character, Integer>();


for ( int i = 0; i < letters.length(); ++i )
{
checkSum.put(letters.charAt(i), primes[i]);
}
return checkSum;
}

Generics only support object types, not primitives. Unlike C++ templates, generics don't involve code generatation and there is only one HashMap code regardless of the number of generic types of it you use.

Trove4J gets around this by pre-generating selected collections to use primitives and supports TCharIntHashMap which to can wrap to support the Map<Character, Integer> if you need to.

TCharIntHashMap: An open addressed Map implementation for char keys and int values.