tags:

views:

164

answers:

7

Hi all, 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:

Map<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?

+2  A: 

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.

Valentin Rocher
+7  A: 

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);
Bozho
This will throw a NullPointerException when the map does not contain the debater.
Thomas Lötzer
+1  A: 

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.

Crozin
+3  A: 

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);
Michael Borgwardt
Neither int nor Integer are classes, they are both types. And both have classes representations: int.class and Integer.class. The difference is: int is a primitive type.
Willi
@Willi: java.lang.Integer is most certainly a class.
Michael Borgwardt
+4  A: 

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.

BalusC
+2  A: 

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.

Thomas Lötzer
+2  A: 

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.

polygenelubricants