Как создать массив коллекции?

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

HashSet<Integer>[] rows = new HashSet<Integer>[9];

дает ошибку компиляции: создание общего массива.

Ответы

Ответ 1

Простой ответ: не смешивать массивы с дженериками!

Используйте список хешсет:

ArrayList<HashSet<Integer>> rows = new ArrayList<HashSet<Integer>>();

Проблема в том, что спецификация Java не позволяет вам объявлять массив объектов generics.

Обходным путем является использование шаблона, но вы потеряете безопасность типа:

HashSet<?>[] rows = new HashSet<?>[9];

for (int i = 0; i < rows.length; ++i)
    rows[i] = new HashSet<Integer>();

Это, в вашем случае, не создаст проблем, когда вы собираетесь проверять, содержится ли элемент: вы можете легко сделать rows[0].contains(4), но при добавлении нового содержимого вы будете вынуждены задавать строку в нужном типе и подавить предупреждение о неконтролируемом произведении:

((HashSet<Integer>)rows[0]).add(4);

Замечание: если вы чувствуете, что пионер просто загружает фреймворк Trove Collections, который имеет не-генерическую, высоко оптимизированную версию integer hashset, выполненный для работы с примитивным типом, я говорю о классе TIntHashSet: он решит вашу проблему и вы получите быстрый код.

Ответ 2

Процитировать Эффективное Java Второе издание Джошуа Блоха, стр. 119

Из-за этих фундаментальных различия, массивы и дженерики не хорошо перемешать. Например, это Запретить создание массива тип общего типа, параметризованный тип или параметр типа. Ни один из этих массивов выражения создания являются законными: new List<E>[], new List<String>[], new E[]. Все приведет к генерическому массиву ошибки создания во время компиляции.

Почему это незаконно, чтобы создать общий массив? Потому что он не является типичным. Если это были законные, броски, сгенерированные компилятор в противном случае программа может выйти из строя во время выполнения с ClassCastException. Это нарушит основная гарантия, предоставляемая система общего типа.

(я пропустил часть, объясняющую стирание стираемого типа)

В главе "Общие" этой книги доступен как PDF.

Ответ 3

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

Set<Integer> rows[] = new HashSet[3];
for (int i = 0; i < rows.length; i++) {
 rows[i] = new HashSet<Integer>();
}

Ответ 4

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

Было бы лучше, если бы он был инкапсулирован в класс обертки? Вероятно, это может сделать вещи менее сложными позже. Через неделю, когда вам придется отлаживать что-то в вашем массиве хэш-массивов arraylists массивов какого-то простого типа данных, потому что вы думали, что просто продолжаете их обертывать, вам будет жаль.

-edit: массивы являются незаконными? Точка отметила. Я все еще чувствую, что аргумент здесь стоит.

Вы используете Java; не бойтесь делать некоторые дополнительные занятия.

public class MyIntegers {
    private HashSet<Integer> theIntegers;

    // wrap methods
    public boolean add(Integer i) { return theIntegers.add(i); }
    public boolean contains(Integer i)...
    public boolean remove(Integer i)...

}

// later...
public static void main(String[] args) {
    MyIntegers[] rows = new MyIntegers[NUM_ROWS];
}