Как "проверить" актерский состав?
Я написал метод, который получает случайное значение из 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);
}
}
Вы можете использовать этот подход и заполнить ваш массив из ключей и значений вашей карты.