开发者

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 Objects.

Also, Now I get a Debater and I need to add 1 to it's its 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜