Безопасный от типа метод varargs, который инициализирует карту - PullRequest
1 голос
/ 28 ноября 2008

Я хочу написать метод, который я могу использовать для инициализации карты. Первый срез:

Map map(Object ... o) {for (int i = 0; i < o.length; i+=2){result.put(o[i], o[i+1])}}

Простой, но не безопасный тип. Используя дженерики, может быть что-то вроде:

<TKey, TValue> HashMap<TKey, TValue> map(TKey ... keys, TValue ... values) 

но этот синтаксис не поддерживается. Итак, в конце концов я пришел к этому:

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;}
}

Но когда я попробую это, мне нужно разыграть это:

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> {}

Может кто-нибудь сказать мне, как кодировать мои методы map (), чтобы он был полностью общим, но не нуждался в приведении?

Ответы [ 3 ]

6 голосов
/ 28 ноября 2008

Чтобы упростить себе жизнь, никогда не используйте тип возврата, содержащий символы подстановки. Типы подстановочных знаков, как правило, предназначены только для параметров метода.

Итак, попробуйте это:

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);
}

Я не проверял это, но попробуйте и посмотрите, как вы поживаете.

P.S., Вместо использования вымышленного Pair типа, вам может быть проще использовать Map.Entry.

1 голос
/ 28 ноября 2008

Почему не это? Я что-то не так понял?

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;
    }
}
0 голосов
/ 30 ноября 2008

pgdx: Ваша техника, безусловно, работает, но она не мешает мне сказать что-то вроде:

Map<Long, Date> map = toHash("hello", "world");

Я искал способ, который позволил бы компилятору обнаруживать любые ошибки несоответствия типов.

...