Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Выбор между Map, Set


Автор: druff 22.1.2008, 16:11
Добрый день!

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

Предположим в субд есть две таблицы, с уникальным набором полей: ТАРИФ (два поля: дата изменения и значение. первичные ключи я опустил, потому что они к делу не относятся) и, скажем, НОРМА (тоже два поля: дата изменения и значение). Необходимо подгрузить эти таблицы в память в виде объектов. Т.е. тоже должно получится два списка, и здесь я не знаю:

1) Что лучше выбрать: хранить дату в качестве ключа, а сам объект будет содержать только значение или же сделать объект с теми же полями из таблицы? В процессе жизни программы в эти списки могут добавляться новые объекты и нужно будет их сортировать заново. В этих списках мне нужен поиск по дате.

2) Из этих двух объектов желательно сформировать ещё один список который должен содержать уникальный набор (дата, значениеТАРИФА, значениеНОРМЫ). Как это лучше реализовать? так же как в пункте 1?

работа с этими коллекциями может совершаться достаточно часто, поэтому скорость работы важна

Автор: nornad 22.1.2008, 17:24
Цитата(druff @  22.1.2008,  19:11 Найти цитируемый пост)
1) Что лучше выбрать: хранить дату в качестве ключа, а сам объект будет содержать только значение или же сделать объект с теми же полями из таблицы? В процессе жизни программы в эти списки могут добавляться новые объекты и нужно будет их сортировать заново. В этих списках мне нужен поиск по дате.

Учитывая возможности расширения списка полей - Map.
Цитата(druff @  22.1.2008,  19:11 Найти цитируемый пост)
2) Из этих двух объектов желательно сформировать ещё один список который должен содержать уникальный набор (дата, значениеТАРИФА, значениеНОРМЫ). Как это лучше реализовать? так же как в пункте 1?

Ключом делаешь объект, содержащий три поля (дата, тариф и норма). И используешь Set, т.к. даже при добавлении новых полей в объект ключа у тебя не появится необходимость хранить данные. А вот если думаешь, что может появиться - тогда Map. Но я бы всё же сделал Set, а уж когда потребуется - заменил бы на Map.

Добавлено через 1 минуту и 4 секунды
Цитата(druff @  22.1.2008,  19:11 Найти цитируемый пост)
работа с этими коллекциями может совершаться достаточно часто, поэтому скорость работы важна

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

Автор: druff 22.1.2008, 17:44
Цитата(nornad @  22.1.2008,  17:24 Найти цитируемый пост)
Ключом делаешь объект, содержащий три поля (дата, тариф и норма). И используешь Set, т.к. даже при добавлении новых полей в объект ключа у тебя не появится необходимость хранить данные. А вот если думаешь, что может появиться - тогда Map. Но я бы всё же сделал Set, а уж когда потребуется - заменил бы на Map.


Не уверен, что правильно понял то, что понимается под термином "ключ" применительно к Set. Можешь пояснить?

Автор: COVD 22.1.2008, 18:31
в основе Set и Map лежит массив Object[]. В обоих случаях при добавлении используется обьект key (ключ) - put(key) для Set или put(key, value) для Map. В Set в массиве сохраняется ссылка на key, в Map - ссылка на обьект value. А индекс, куда положить ссылку, вычисляется по хешкоду обьекта key.     

Автор: druff 24.1.2008, 15:58
Упс. Значит это я недопонял документацию. 

Я посчитал, что реализовав интерфейс Comparable в своём классе из двух полей (дата и значение) смогу сделать поиск в коллекции своих объектов по дате. Однако тот же binarySearch всё равно требует в качестве параметра объект, а дату брать отказывается :(

Значит поиск нужно реализовывать самому?

Автор: druff 24.1.2008, 16:17
Или же можно создать фиктивный объект, присвоить ему нужную дату и делать поиск по этому объекту?

Автор: LSD 24.1.2008, 17:02
Цитата(druff @  24.1.2008,  15:58 Найти цитируемый пост)
Я посчитал, что реализовав интерфейс Comparable в своём классе из двух полей (дата и значение) смогу сделать поиск в коллекции своих объектов по дате. Однако тот же binarySearch всё равно требует в качестве параметра объект, а дату брать отказывается :(

На самом деле можешь, просто надо сделать типа такого:
Код

public class SomeData implements Comparable
{
  private Date date;
....

  public int compareTo(Object o)
  {
    if(o instanceof Date)
      return ((Date) o).compareTo(this.date);
    SomeData that = (SomeData) o;
    return this.date.compareTo(that.date);
  }
}

хотя это и будет нарушением контракта.

Автор: druff 24.1.2008, 17:14
Попробовал сделать как в примере - всё равно не даёт. В binarySearch всё же можно скармливать ключ только того же типа, что и элементы в коллекции. Зато с фиктивным объектом всё получилось и заработало.

Если вначале склонялся к Set или Map, то сейчас выяснил, что средств поиска у них вообще нет (только переводить в массив). Поэтому буду работать с List

Автор: LSD 24.1.2008, 17:22
Цитата(druff @  24.1.2008,  17:14 Найти цитируемый пост)
Попробовал сделать как в примере - всё равно не даёт. В binarySearch всё же можно скармливать ключ только того же типа, что и элементы в коллекции. Зато с фиктивным объектом всё получилось и заработало.

Уж не знаю, что ты пробовал:
Код

public class SomeData implements Comparable
{
  private Date date;

  public int compareTo(Object o)
  {
    if(o instanceof Date)
      return ((Date) o).compareTo(this.date);
    SomeData that = (SomeData) o;
    return this.date.compareTo(that.date);
  }

  public static void main(String[] args)
  {
    SomeData[] data = new SomeData[3];

    long now = System.currentTimeMillis();
    data[0] = new SomeData();
    data[0].date = new Date(now - 10);

    data[1] = new SomeData();
    data[1].date = new Date(now);

    data[2] = new SomeData();
    data[2].date = new Date(now + 10);

    int i = Arrays.binarySearch(data, new Date(now));
    System.out.println("i = " + i);
  }
}

Выдаёт 1 как и ожидалось.

Автор: druff 24.1.2008, 17:30
О, действительно

если создавать список как
Код

List<Tariff> tariffArrayList = new ArrayList();

то на binarySearch с поиском по дате выдаёт ошибку, а если
Код

List tariffArrayList = new ArrayList();

то ошибки нет

Автор: LSD 24.1.2008, 17:32
А нет, ошибка все таки есть, но она в другом:
Код

  public int compareTo(Object o)
  {
    if(o instanceof Date)
      return this.date.compareTo((Date) o);
    SomeData that = (SomeData) o;
    return this.date.compareTo(that.date);
  }

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)