I'm wanting to write a method that I can use to initialise a Map. First cut:
我想写一个可以用来初始化Map的方法。首裁:
Map map(Object ... o) {for (int i = 0; i < o.length; i+=2){result.put(o[i], o[i+1])}}
Simple, but not type-safe. Using generics, maybe something like:
简单,但不是类型安全的。使用泛型,可能是这样的:
<TKey, TValue> HashMap<TKey, TValue> map(TKey ... keys, TValue ... values)
but that syntax isn't supported. So eventually I come to this:
但是不支持该语法。所以最终我来到这里:
public static <TKey, TValue, TMap extends Map<? super TKey, ? super TValue>> TMap map(TMap map, Pair<? extends TKey, ? extends TValue> ... pairs) {
for (Pair<? extends TKey, ? extends TValue> pair: pairs) {
map.put(pair.getKey(), pair.getValue());
}
return map;
}
public static <TKey, TValue> HashMap<? super TKey, ? super TValue> map(Pair<? extends TKey, ? extends TValue> ... pairs) {
return map(new HashMap<TKey, TValue>(), pairs);
}
public static <TKey, TValue> Pair<TKey, TValue> pair(TKey key, TValue value) {
return new Pair<TKey, TValue>(key, value);
}
public static final class Pair<TKey, TValue> {
private final TKey key;
private final TValue value;
Pair(TKey key, TValue value) {this.key = key; this.value = value; }
public TKey getKey() {return key;}
public TValue getValue() {return value;}
}
But when I try it out, I need to cast it:
但是当我试一试时,我需要施展它:
private static final Map<? extends Class<? extends Serializable>, ? super TypeHandler<? extends Serializable > > validCodeTypes =
/* (Map<? extends Class<? extends Serializable>, ? super TypeHandler<? extends Serializable >>) */
map(
pair(Integer.class, new IntHandler()),
pair(Integer.TYPE, new IntHandler()),
pair(Character.class, new CharHandler()),
pair(Character.TYPE, new CharHandler()),
pair(String.class, new StringHandler())
);
private interface TypeHandler<TType extends Serializable> {}
private static class CharHandler implements TypeHandler<Character> {}
private static class IntHandler implements TypeHandler<Integer> {}
private static class StringHandler implements TypeHandler<String> {}
Can anyone tell me how to code my map() methods so that it is entirely general yet doesn't need to be casted?
任何人都可以告诉我如何编码我的map()方法,以便它是完全通用的,但不需要进行转换?
3 个解决方案
#1
6
To make life easier for yourself, never use a return type that contains wildcards. Wildcard types, in general, are for method parameters only.
为了让自己的生活更轻松,请不要使用包含通配符的返回类型。通常,通配符类型仅用于方法参数。
So, try this:
所以,试试这个:
public static <TKey, TValue, TMap extends Map<TKey, TValue>> TMap map(TMap map, Pair<? extends TKey, ? extends TValue>... pairs) {
for (Pair<? extends TKey, ? extends TValue> pair: pairs) {
map.put(pair.getKey(), pair.getValue());
}
return map;
}
public static <TKey, TValue> HashMap<TKey, TValue> map(Pair<? extends TKey, ? extends TValue>... pairs) {
return map(new HashMap<TKey, TValue>(), pairs);
}
I haven't tested it, but give it a go and see how you fare.
我没有测试过,但是试一试,看看你的表现如何。
P.S., rather than using a made-up Pair
type, you may find it easier to use Map.Entry
.
P.S.,而不是使用伪造的Pair类型,您可能会发现使用Map.Entry更容易。
#2
1
Why not this? Did I misunderstand something?
为什么不呢?我误解了什么吗?
import java.util.HashMap;
import java.util.Map;
public class ToHash {
public static <K, V> Map<K, V> toHash(Object... objects) {
Map<K, V> map = new HashMap<K, V>(objects.length / 2);
if (objects.length % 2 != 0) {
throw new IllegalArgumentException("Odd number of elements: " + objects.length);
}
for (int i = 0; i < objects.length; i += 2) {
map.put((K) objects[i], (V) objects[i + 1]);
}
return map;
}
}
#3
0
pgdx: Your technique certainly works but it does not prevent me from saying something like:
pgdx:你的技术当然有效,但它并没有阻止我说出类似的话:
Map<Long, Date> map = toHash("hello", "world");
I was looking for a way which would allow the compiler to pick up on any type-mismatch errors.
我一直在寻找一种允许编译器接收任何类型不匹配错误的方法。
#1
6
To make life easier for yourself, never use a return type that contains wildcards. Wildcard types, in general, are for method parameters only.
为了让自己的生活更轻松,请不要使用包含通配符的返回类型。通常,通配符类型仅用于方法参数。
So, try this:
所以,试试这个:
public static <TKey, TValue, TMap extends Map<TKey, TValue>> TMap map(TMap map, Pair<? extends TKey, ? extends TValue>... pairs) {
for (Pair<? extends TKey, ? extends TValue> pair: pairs) {
map.put(pair.getKey(), pair.getValue());
}
return map;
}
public static <TKey, TValue> HashMap<TKey, TValue> map(Pair<? extends TKey, ? extends TValue>... pairs) {
return map(new HashMap<TKey, TValue>(), pairs);
}
I haven't tested it, but give it a go and see how you fare.
我没有测试过,但是试一试,看看你的表现如何。
P.S., rather than using a made-up Pair
type, you may find it easier to use Map.Entry
.
P.S.,而不是使用伪造的Pair类型,您可能会发现使用Map.Entry更容易。
#2
1
Why not this? Did I misunderstand something?
为什么不呢?我误解了什么吗?
import java.util.HashMap;
import java.util.Map;
public class ToHash {
public static <K, V> Map<K, V> toHash(Object... objects) {
Map<K, V> map = new HashMap<K, V>(objects.length / 2);
if (objects.length % 2 != 0) {
throw new IllegalArgumentException("Odd number of elements: " + objects.length);
}
for (int i = 0; i < objects.length; i += 2) {
map.put((K) objects[i], (V) objects[i + 1]);
}
return map;
}
}
#3
0
pgdx: Your technique certainly works but it does not prevent me from saying something like:
pgdx:你的技术当然有效,但它并没有阻止我说出类似的话:
Map<Long, Date> map = toHash("hello", "world");
I was looking for a way which would allow the compiler to pick up on any type-mismatch errors.
我一直在寻找一种允许编译器接收任何类型不匹配错误的方法。