Map generics in Java
I seem to have a bit of misunderstanding with Java Generics and I hope you can help me. I tried to create a map like so:
Map<Debater, int>
(Debater is an Interface I declared) but java complained about the int, so I did:
M开发者_C百科ap<Debater, Integer>
I suppose it's because int is not a class while Integer is, is this correct?
Also, Now I get a Debater and I need to add 1 to its value in the map. How do I do that?
Yes, you are correct.
As for incrementing:
map.put(debater, map.get(debater) + 1);
Autoboxing will take care of "switching" between the object and the primitive.
Note that this (as noted in the comments) will throw a NullPointerException
if you don't have a value for this debater in the map already. So if you want to do 2-in-1, it can be reworked as follows:
map.put(debater, map.containsKey(debater) ? map.get(debater) + 1 : 1);
That's correct. A Map
can only hold Object
s.
Also, Now I get a Debater and I need to add 1 to
it'sits value in the map. How do I do that?
I suggest you to grab AtomicInteger
for that so that it's more failsafe in case of multithreaded environments.
Map<Debater, AtomicInteger> map = new HashMap<Debater, AtomicInteger>();
// ...
map.get(debater).incrementAndGet();
Else you'll need to add more code to synchronize
the update to avoid that threads get the "wrong" value.
I suppose it's because int is not a class while Integer is, is this correct?
Correct.
Also, Now I get a Debater and I need to add 1 to it's value in the map. How do I do that?
This should do the trick:
map.put(debater, map.get(debater)+1);
You're right, it's because you have to specify a class.
As for your question, you juste have to do :
myMap.put(myDebater, myMap.get(myDebater) + 1);
All conversions between int and Integer will be done by autoboxing.
You are correct about the int vs. Integer part.
To increment the value safely use:
Integer currentValue = map.get(debater);
if(currentvalue == null) {
map.put(debater, 1);
} else {
map.put(debater, currentValue + 1);
}
or you could use map.contains(debater)
first if you want to handle the case that a debater is not contained in the map separately.
Java does not allow primitive types in generics. Fortunately, each of the primitive types has a "box" reference type, e.g. Integer
for int
, Boolean
for boolean
, etc. The language is aware of this association, and can do automatic boxing and unboxing for you. This means that you can do something like this:
Integer i = 5;
i++;
There are some caveats with automatic boxing/unboxing that you have to be aware of. The classic example is the following:
List<Integer> list = new ArrayList<Integer>();
list.add(3); // this is autoboxed, and calls list.add(E)
list.remove(3); // this invokes list.remove(int) overload !!!!
list.remove((Integer) 3) // this is how you call list.remove(E)
You will find that the above code as is will throw IndexOutOfBoundsException
, because the first remove
tries to remove the 3rd element, instead of the element 3.
You cannot use primitive type (such as int
, float
, char
etc.) as a generic type - collections in Java are generic. That's why you have to use Integer
instead of int
.
精彩评论