Generics, damned if you do, damned if you don't

R

Roedy Green

Consider this code snippet:

// create a new HashMap
HashMap<String, Integer> h = new HashMap<String, Integer>(149, .75f);
....

// extract key/value pair entries into an array
Set<Map.Entry<String, String>> justEntries = h.entrySet();
Map.Entry<String, String>[] keyValuePairs =
justEntries.toArray ( new Map.Entry[justEntries.size()] );

This generates an "unchecked conversion" warning.

If put in the type like this:

// extract key/value pair entries into an array
Set<Map.Entry<String, String>> justEntries = h.entrySet();
Map.Entry<String, String>[] keyValuePairs =
justEntries.toArray ( new
Map.Entry<String,String>[justEntries.size()] );

I get an "generic array conversion error"

How are you supposed to code that.

Map.Entry is an interface and HashMap.Entry is not public. However
the problem appears to be general -- even creating arrays af HashMaps.
 
J

Joshua Cranmer

Consider this code snippet:

// create a new HashMap
HashMap<String, Integer> h = new HashMap<String, Integer>(149, .75f);
...

// extract key/value pair entries into an array
Set<Map.Entry<String, String>> justEntries = h.entrySet();
Don't you mean Map.Entry said:
Map.Entry<String, String>[] keyValuePairs = justEntries.toArray
( new Map.Entry[justEntries.size()] );

This generates an "unchecked conversion" warning.
How are you supposed to code that.

Go with the first one, bite the bullet, and add a @SuppressWarnings
("unchecked") in. Arrays + generics don't mix. In the Sun generics FAQ,
there's a part about why there are such problems with generic arrays
(simple answer: type erasure).
 
E

Eric Sosman

Roedy Green wrote On 07/02/07 17:01,:
Consider this code snippet:

// create a new HashMap
HashMap<String, Integer> h = new HashMap<String, Integer>(149, .75f);
...

// extract key/value pair entries into an array
Set<Map.Entry<String, String>> justEntries = h.entrySet();
Map.Entry<String, String>[] keyValuePairs =
justEntries.toArray ( new Map.Entry[justEntries.size()] );

This generates an "unchecked conversion" warning.

If put in the type like this:

// extract key/value pair entries into an array
Set<Map.Entry<String, String>> justEntries = h.entrySet();
Map.Entry<String, String>[] keyValuePairs =
justEntries.toArray ( new
Map.Entry<String,String>[justEntries.size()] );

I get an "generic array conversion error"

How are you supposed to code that.

Map.Entry is an interface and HashMap.Entry is not public. However
the problem appears to be general -- even creating arrays af HashMaps.

You may find

http://www.angelikalanger.com/Gener...ncrete instantiation of a parameterized type?

and

http://www.angelikalanger.com/Gener...w do I generically create objects and arrays?

helpful.
 
B

Bart

...
I get an "generic array conversion error"

How are you supposed to code that.
...

AFAIK, there's no "generics" way to do this, suppressing it is the
only way unfrtunatelly, I guess.

...
even creating arrays af HashMaps.
...

You mean like this?

HashMap<String, Integer> h = new HashMap<String, Integer>();
String[] keys = h.keySet().toArray(new String[]{});
Integer[] values = h.values().toArray(new Integer[]{});

which gives no compiler errors/warnings (with Eclpise's compiler, that
is).

Regards,
Bart.
 
T

Tom Hawtin

Roedy said:
// create a new HashMap
HashMap<String, Integer> h = new HashMap<String, Integer>(149, .75f);
...

// extract key/value pair entries into an array
Set<Map.Entry<String, String>> justEntries = h.entrySet();
Map.Entry<String, String>[] keyValuePairs =
justEntries.toArray ( new Map.Entry[justEntries.size()] );
Map.Entry is an interface and HashMap.Entry is not public. However
the problem appears to be general -- even creating arrays af HashMaps.


Avoid arrays of reference types. We now have the much nicer generic List.

So the code becomes:

List<Map.Entry<String,String>> entries =
new java.util.ArrayList<Map.Entry<String,String>>(
map.entrySet();
);

Tom Hawtin
 
R

Roedy Green

You mean like this?

HashMap<String, Integer> h = new HashMap<String, Integer>();
String[] keys = h.keySet().toArray(new String[]{});
Integer[] values = h.values().toArray(new Integer[]{});

which gives no compiler errors/warnings (with Eclpise's compiler, that
is).
no. You don't allocate any arrays of generics there. See
http://mindprod.com/jgloss/hashmap.html
for sample code.
 
B

Bart

...
HashMap<String, Integer> h = new HashMap<String, Integer>();
String[] keys = h.keySet().toArray(new String[]{});
Integer[] values = h.values().toArray(new Integer[]{});
which gives no compiler errors/warnings (with Eclpise's compiler, that
is).

no. You don't allocate any arrays of generics there.

I don't get your point. What IS it that I do then?

From you webpage:

// extract the keys into an array
Set<String> justKeys = h.keySet();
// Use toArray that takes an empty array,
// otherwise we end up with a useless Object[] instead of a
String[].
String[] keys = justKeys.toArray( new
String[justKeys.size()] );

How is the above different than the code I posted?

Regards,
Bart.
 
B

Bart

...
How is the above different than the code I posted?
...

Besides the fact that you explicitly say how many elements the newly
created array should have, whereas I leave that responsibility to
Arrays' toString() method, of course.
 
R

Roedy Green

From you webpage:

// extract the keys into an array
Set<String> justKeys = h.keySet();
// Use toArray that takes an empty array,
// otherwise we end up with a useless Object[] instead of a
String[].
String[] keys = justKeys.toArray( new
String[justKeys.size()] );

How is the above different than the code I posted?

It is not different. It just not the problem we were talking about,
arrays of generics. Look in the code sample about autoboxing.
 
R

Roedy Green

It is not different. It just not the problem we were talking about,
arrays of generics. Look in the code sample about autoboxing.

The code you quoted is an array of ordinary Strings, not an array of
generics. The problem comes here when you try to allocate an array of
generics:

// extract key/value pair entries into an array
Set<Map.Entry<String, Integer>> justEntries =
h.entrySet();
// Infuriatingly, this generates an unchecked conversion
warning message.
Map.Entry<String, Integer>[] keyValuePairs =
justEntries.toArray( new
Map.Entry[justEntries.size()] );
// Type erasure won't let us say:
// Map.Entry<String, Integer>[] keyValuePairs =
// justEntries.toArray ( new
// Map.Entry<String,Integer>[justEntries.size()] );
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,012
Latest member
RoxanneDzm

Latest Threads

Top