Как реализовать отношение n: m в Java? - PullRequest
6 голосов
/ 13 октября 2010

Мне нужно реализовать отношение n: m в Java. Вариант использования - это каталог.

  • товар может быть нескольких категорий
  • категория может содержать несколько продуктов

Мое текущее решение состоит в том, чтобы иметь класс отображения, который имеет две хеш-карты.

  • Ключ первой хэш-карты - это идентификатор продукта, а значение - список идентификаторов категории
  • Ключом ко второй хэш-карте является идентификатор категории, а значением - список идентификаторов продуктов

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

Но я нашел единственный способ сделать следующий перманент в O (1) :

  • Какая продукция принадлежит категории?
  • В каких категориях находится товар?

Я хочу избегать полных сканирований массивов или чего-либо подобного во всех отношениях.

Но должно быть другое, более элегантное решение, в котором мне не нужно дважды индексировать данные.

Пожалуйста, просветите меня. У меня есть только обычная Java, нет базы данных, SQLite или чего-то доступного. Я также не хочу реализовывать структуру btree, если это возможно.

Ответы [ 4 ]

6 голосов
/ 13 октября 2010

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

public class Product {
     private Set<Category> categories = new HashSet<Category>();
     //implement hashCode and equals, potentially by id for extra performance
}

public class Category {
     private Set<Product> contents = new HashSet<Product>();
     //implement hashCode and equals, potentially by id for extra performance
}

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

Но подход к использованию вспомогательных хэш-карт / деревьев для индексации не является плохим.В конце концов, большинство индексов, размещенных, например, в базах данных, являются вспомогательными структурами данных: они сосуществуют с таблицей строк;строки не обязательно организованы в структуре самого индекса.

Использование такой внешней структуры дает вам возможность хранить оптимизации и данные отдельно друг от друга;это не плохоОсобенно, если завтра вы захотите добавить O (1) поиска для продуктов, предоставленных Продавцом, например,

Редактировать: Кстати, похоже, что вы хотитереализация Multimap , оптимизированной также для выполнения обратного поиска в O (1).Я не думаю, что Guava может что-то сделать, но вы могли бы реализовать интерфейс Multimap, чтобы, по крайней мере, вам не приходилось иметь дело с поддержкой HashMaps отдельно. На самом деле это больше похоже на BiMap, который также является Multimap, которыйпротиворечиво, учитывая их определения.Я согласен с MStodd, что вы, вероятно, хотите создать свой собственный слой абстракции для инкапсуляции двух карт.

3 голосов
/ 13 октября 2010

Ваше решение отлично. Помните, что помещение объекта в HashMap не делает копию объекта, он просто хранит ссылку на него, поэтому затраты времени и памяти довольно малы.

1 голос
/ 13 октября 2010

Я бы пошел с вашим первым решением.Создайте слой абстракции вокруг двух хэш-карт.Если вас беспокоит параллелизм, установите соответствующую блокировку для CRUD.

0 голосов
/ 28 августа 2016

Если вы можете использовать неизменную структуру данных, в Guava ImmutableMultimap предлагается метод inverse(), который позволяет получить набор ключей по значению.

...