Reputation: 927
I have a method to get the contents of the Map as a String, like this:
public static String toStringStringFloatMap(Map<String, Float> stringFloatMap)
{
String entries = "";
Iterator<Entry<String, Float>> it = stringFloatMap.entrySet().iterator();
while (it.hasNext())
{
Map.Entry<String, Float> pair = it.next();
entries += pair.getKey() + "=" + pair.getValue() + "\n";
}
return entries;
}
Now I am trying to convert it to a generic version for Integer, Short, Double, .... . I have replaced all Float with "? extends Number" but the ....entrySet().iterator(); statement causes compile error and tells me the following:
Type mismatch: cannot convert from Iterator<Map.Entry<String,capture#6-of ? extends Number>> to Iterator<Map.Entry<String,? extends Number>>
I don't know what that "captured#6-of ? extends Number" means. anyone can explain it for me?
EDIT:
As Andy points out that the <?, ?>
may be the best.
But my question is still that why the iterator() line cannot pass the compiler?
public static String toStringMapError(Map<?, ?> map)
{
String entries = "";
Iterator<Entry<?, ?>> it = map.entrySet().iterator(); <<<<<------- error lineeeeeee
while (it.hasNext())
{
Map.Entry<?, ?> pair = it.next();
entries += pair.getKey() + "=" + pair.getValue() + "\n";
}
return entries;
}
Upvotes: 3
Views: 536
Reputation: 12953
You shouldn't replace Float
with ? extends Number
, instead, define a generic type in your method and use it:
public static <T extends Number> String toStringStringFloatMap(Map<String, T> stringFloatMap)
{
String entries = "";
Iterator<Map.Entry<String, T>> it = stringFloatMap.entrySet().iterator();
while (it.hasNext())
{
Map.Entry<String, T> pair = it.next();
entries += pair.getKey() + "=" + pair.getValue() + "\n";
}
return entries;
}
Upvotes: 2
Reputation: 140494
If you really want to constrain to subclasses of Number
, declare a type variable, and use throughout:
public static <T extends Number> String toStringStringNumberMap(Map<String, T> stringFloatMap) {
String entries = "";
Iterator<Entry<String, T>> it = stringNumberMap.entrySet().iterator();
while (it.hasNext())
{
Map.Entry<String, T> pair = it.next();
entries += pair.getKey() + "=" + pair.getValue() + "\n";
}
return entries;
}
But you could simply use ?
for both the key and value: there's nothing here that requires an instance of String
or Number
specifically: all you need is types implementing toString()
, which means any subclass of Object
is acceptable.
public static String toStringMap(Map<?, ?> map) { ... }
You can also use an enhanced for statement, which is neater than an explicit iterator; and you should always use a StringBuilder
when accumulating strings in a loop, and avoid building unnecessary temporary strings:
StringBuilder sb = new StringBuilder();
for (Map.Entry<?, ?> entry : map.entrySet()) {
sb.append(entry.getKey());
sb.append('=');
sb.append(entry.getValue());
sb.append('\n');
}
return sb.toString();
Upvotes: 8