Java: имеющие версию структуры данных?

У меня есть структура данных, которая довольно проста (в основном структура, содержащая некоторые массивы и единственные значения), но я должен записать историю структуры данных так, чтобы я мог эффективно получить содержание структуры данных в любом моменте времени.

Существует ли относительно простой способ сделать это?

Лучшим способом я могу думать, должен был бы инкапсулировать целую структуру данных с чем-то, что обрабатывает все операции видоизменения, храня данные в функциональных структурах данных, и затем для каждой операции мутации, кэширующей копию структуры данных в Карте, индексированной упорядочиванием времени (например, TreeMap с реальным временем как ключи или HashMap со счетчиком операций мутации, объединенных с одним или несколькими индексами, сохраненными в TreeMaps, отображающем реальное время / количество галочки / и т.д. к операциям мутации)

какие-либо предложения?

править: В одном случае у меня уже есть история как ряд транзакций (это читает объекты из файла данных), таким образом, я могу воспроизвести их, но это берет O (n) шаги (n = # транзакций) каждый раз, когда я должен получить доступ к данным. Я ищу альтернативы.

9
задан Community 23 May 2017 в 12:31
поделиться

6 ответов

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

Я создал Java-библиотеку таких структур данных с открытым исходным кодом здесь:

http://code.google.com/p/mikeralib/source/browse/#svn/trunk/Mikera/src/mikera/persistent

​​Они были в некоторой степени вдохновлены постоянными структурами данных Clojure, которые также могут быть подходящими для ваших целей (они также написаны на Java).

2
ответ дан 5 December 2019 в 01:42
поделиться

Вы правы. Лучше всего хранить данные в чисто функциональной структуре данных. Поддержка чего-либо умеренно сложного с помощью действий do / undo зависит от того, знает ли программист обо всех побочных эффектах каждой операции, которая не масштабируется и нарушает инкапсуляцию.

3
ответ дан 5 December 2019 в 01:42
поделиться

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

0
ответ дан 5 December 2019 в 01:42
поделиться

Если вы храните только небольшой объем данных и не вносите много изменений, тогда можно сохранить каждую версию.

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

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

Итак, вы начинаете с пустой структуры данных и можете получить инструкцию «Добавить», за которой следует «Изменить», еще одно «добавить», а затем, возможно, «Удалить». Каждый из этих объектов будет содержать КОПИЮ (а не указатель на тот же объект) добавляемой или изменяемой вещи.

Вы должны объединить каждую операцию в список и в то же время изменить свою коллекцию.

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

Если это было очень долгое приложение, и вам часто приходилось обращаться к элементам ближе к концу, вы могли бы написать «Отменить» для каждого объекта операции добавления / изменения / удаления и фактически изменить данные туда и обратно.

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

Вы даже можете содержать несколько объектов данных, просто создайте новый пустой и запускайте его в массиве мутаций (думайте об этом как о временной шкале - где каждая сохраненная мутация будет содержать метку времени или некоторый номер версии), пока вы не получите ее. к нужной временной метке - таким образом у вас могут быть «вехи», которых вы могли бы достичь мгновенно - например, если вы выделили одну веху для каждого потока, вы могли бы синхронизировать метод addMutation, и этот сбор данных стал бы на 100% потокобезопасным.

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

Хм, вы также можете включить функцию «Rollup» - если вы когда-нибудь решите, что вам не понадобится доступ к хвосту (первые несколько транзакций), вы можете применить их к структуре «Start», а затем удалить их - с этого момента вы копируете начальную структуру, чтобы начать с начала, а не всегда начинать с пустой структуры данных.

Чувак, это потрясающий паттерн - теперь я хочу его реализовать.

0
ответ дан 5 December 2019 в 01:42
поделиться

Многоуровневая отмена может быть основана на модели (т.е. структуре данных) и последовательности действий. Каждое действие поддерживает две операции: "сделать" и "отменить". Чтобы выполнить изменение в модели, вы регистрируете новое действие и "делаете" его. Это позволяет вам "ходить" взад и вперед по истории, но к состоянию модели в определенном индексе нельзя получить доступ в постоянном времени.

Может быть, что-то подобное применимо к вашей ситуации?

.
-1
ответ дан 5 December 2019 в 01:42
поделиться

Как долго приложение будет работать?

Похоже, вы могли бы сделать то, что предлагали, - воспроизвести транзакции обратно, - но кэшировать структуру данных и список транзакций в определенные моменты времени (каждый час или каждый день?), Чтобы облегчить боль от необходимости идти с помощью O (n) операций каждый раз, когда вам нужно перестроить коллекцию с нуля.

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

-1
ответ дан 5 December 2019 в 01:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: