Как "проверить" актерский состав?

Я написал метод, который получает случайное значение из Map, Сначала я получил все значения на карте и использую Random объект, чтобы получить случайный. Вот метод:

public static <K, V> V getRandomValInMap (Map<K, V> map) {
    Collection<V> values = map.values ();
    V[] array = (V[])values.toArray ();
    return array[random.nextInt (array.length)];
}

В выражении

(V[])values.toArray ()

Android Studio заявила, что это "непроверенный актерский состав из Object[] в V[]"Так что я думаю, что это" рискованно ". Я пытался использовать другую перегрузку toArray:

V[] array = new V[values.size()];
array = values.toArray (array);

И я думаю, что это не то, как вы бы использовали перегрузку, потому что есть ошибка компилятора, говорящая, что я не могу инициализировать V,

Поэтому я думаю, может быть, я должен использовать первый метод. Но как мне "проверить" приведение, чтобы отменить предупреждение?

Или вы можете сказать мне, как использовать toArray(T[] array) перегрузка правильно.

5 ответов

Решение

Лучше было бы вообще не создавать новый массив:

public static <K, V> V getRandomValInMap (Map<K, V> map) {
    Collection<V> values = map.values ();

    Iterator<V> it = values.iterator();
    int choosen = new Random().nextInt (values.size());
    for (int i=0; i<values.size();i++) {
        V value = it.next();
        if (i==choosen) return value;
    }
    throw new AssertionError("Choosen value out of bounds");
}

Вы не можете создать массив универсального типа, это известное ограничение в Java, и для этого есть веские причины. Так что это невозможно: V[] array = new V[values.size()];

Смотрите также:

По какой причине я не могу создать универсальные типы массивов в Java?

В Java есть стирание типа. При компиляции универсальный тип будет удален и обработан как Object тип.

Вы можете подавить предупреждение:

public static <K, V> V getRandomValInMap (Map<K, V> map) {
    Collection<V> values = map.values ();
    @SuppressWarnings("unchecked") V[] array = (V[])values.toArray ();
    return array[1];
}

Вы можете проверить это во время выполнения, используя instanceof, но если вы знаете, что на карте будет отображаться только правильный тип объектов, вам следует просто оставить все как есть - исправление предупреждения с ненужными накладными расходами во время выполнения - плохая идея. Это предупреждение в основном означает, что нет никакого способа быть уверенным, что вы всегда получаете правильные объекты с карты.

new V не работает из-за стирания типа. Это было дизайнерское решение в Java, чтобы сохранить обратную совместимость, когда были представлены дженерики.

Если вы заботитесь только о предупреждении, вы, конечно, можете его подавить.

Цитирование Брюса Экеля в Thinking in Java с использованием Array.newInstance является рекомендуемым подходом для создания массивов в обобщениях.

public class ArrayMaker<T> { 
 private Class<T> kind; 
 public ArrayMaker(Class<T> kind) { this.kind = kind; } 
 @SuppressWarnings("unchecked") 
 T[] create(int size) { 
  return (T[])Array.newInstance(kind, size); 
 }
}

Вы можете использовать этот подход и заполнить ваш массив из ключей и значений вашей карты.

Другие вопросы по тегам