Дженерики и TreeSets - PullRequest
       23

Дженерики и TreeSets

0 голосов
/ 01 февраля 2011

Работа с дженериками, безусловно, является моим слабым местом, и в этом может помочь некоторая помощь.

Проект состоит в разработке простой системы заказов / инвентаризации, которая размещает заказы, отслеживает предметы и запасы и сохраняетзапись всего инвентаря и добавление / удаление клиентов с момента первого запуска программы.Это требует чтения и записи в файл, и я выбрал формат CSV для анализа.Есть два файла для анализа, один для Customers и один для Items.

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

Единственное решение, которое я нашел, это TreeSet<? extends Object>, но это означает, что мне придется блокировать, а затем распаковывать каждый объект при обращении к нему в структуре.

Есть ли более простой способ?

Ответы [ 4 ]

4 голосов
/ 01 февраля 2011

Вот пример того, как ваша иерархия может выглядеть

class CVSParser<T> {
    private final RecordHandler<T> handler;

    public CVSParser<T>(RecordHandler<T> handler) {
       this.handler = handler;
    }

    public Set<T> parse(File f) {
        Set<T> records = new TreeSet<T>();
        for (String line : file ) {  //I'm paraphrasing here
           records.add(handler.parse( splitIntoFields(line) ));
        }
    }
}

interface RecordHandler<T> {
    public T parse(String[] fields);
}

class CustomerHandler implements RecordHandler<Customer> {
   public Customer parse(String[] fields) {
      return new Customer(fields[0], fields[1]);
   }
}

class ItemHandler implements RecordHandler<Item> {
   //...
}

Set<Item> items = new CVSParser<Item>(new ItemHandler()).parse(itemsFile);

В качестве альтернативы вы можете опустить дженерики до уровня метода CVSParser и сделать его статическим даже:

class CVSParser {
     public static <T> Set<T> parse(RecordHandler<T> handler, File f) {
        //...        
     }
}


Set<Item> items = CVSParser.parse(new ItemHandler(), itemsFile);
2 голосов
/ 01 февраля 2011

Вы ищете

interface CSVParseableObject {
   // routines
}

public class Customers implements CSVParseableObject{}
public class Items implements CSVParseableObject{}

А потом

TreeSet<CSVParseableObject>

В котором вы можете разобрать, например,

Set<CSVParseableObject> parse(String path) {
    Set<CSVParseableObject> parseableObjects = new TreeSet<CSVParseableObject>();
    File file = new File(path);
    // parse ... 
    return parseableObjects;
}
0 голосов
/ 01 февраля 2011

Думаю, вы действительно растеряны.

Каждый файл представляет данные из разных типов объектов (Клиенты и Предметы), поэтому их форматы различны, как и их поля. Вы не можете иметь один и тот же код, чтобы проанализировать их оба.

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

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

Вы можете сделать что-то подобное в своем коде:

class MyParser {
    public Set<Customer> readCustomersFile(String path) {...}
    public Set<Item> readItemsFile(String path) {...}
}

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

0 голосов
/ 01 февраля 2011

Вот вариант:

Создайте класс для представления элемента инвентаризации и сделайте так, чтобы он расширял или (лучше) реализовывал ваш интерфейс синтаксического анализа.Таким образом, вы можете просто вставить объект Inventory в ваше дерево.

Например, TreeSet<Inventory> tree = TreeSet<Inventory>() tree.add (Inventory Object) и т. Д.

...