Я хочу сравнить две похожие структуры объектов и перечислить разницу - PullRequest
0 голосов
/ 13 марта 2019

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

Каждый предлагает метод отражения. Метод отражения мне не помогает, я попробовал. Моя структура объекта слишком сложна.

Ниже моя структура объекта. Объект, содержащийся в списке, не может быть в том же порядке в другом списке. один список может иметь этот объект, другой объект может не иметь этого списка.

Структура:

объект
-Field
-Field
-Field
Список
-Объект
-объект
-объект
-Список
-объект
-Field
-Field
-объект
-Field
-Field
-Field
-Field
-Список
-объект
-Field
-Field
-объект
-Field
-Field

Ответы [ 3 ]

1 голос
/ 13 марта 2019

API отражения

Я бы все же предложил посмотреть на Java Reflection . См. Википедия .

Например, вы можете сделать рекурсивный вызов с Reflection, если атрибут сам объект, и тем самым ввести его тем же методом.

public void determineObjectStructure (Object o) {

    Field[] fields = o.getClass().getDeclaredFields();
    for (Field field : fields) {
        // Check Type of field

        // If not primitive -> determineObjectStructure()

        // create Representation
        }
    }

Затем вы можете вручную создать представление «структура сложного объекта», которое содержит, например, список с:

levelInComplexObject | объект

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

0 голосов
/ 13 марта 2019

ANTLR

Проект ANTLR представляет собой набор сложных инструментов для анализа исходного кода. См. Википедия .

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

Вы вводите эту грамматику в ANTLR. Выходит исходный код для лексера, который распознает слова файла исходного кода, и анализатор для распознавания фраз и операторов файла исходного кода.

Вы компилируете эти сгенерированные исходные файлы. Затем скормите ваши исходные файлы Java. Выходит абстрактное синтаксическое дерево, структура данных, представляющая содержимое исходного кода Java. Вы можете легко обходить это дерево, собирая части (имя класса, переменные-члены, методы, аргументы, локальные переменные и т. Д.) По ходу работы.

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

ANTLR является открытым исходным кодом и бесплатной.

См. Превосходное руководство и справочник, написанный основным создателем ANTLR, Теренс Парр , озаглавленный Полное руководство по ANTLR 4 .

0 голосов
/ 13 марта 2019

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

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

Простой пример может быть:

@Test
public void shouldCompareTwoEntities() {
  //given
  Javers javers = JaversBuilder.javers()
          .withListCompareAlgorithm(LEVENSHTEIN_DISTANCE)
          .build();

  Employee frodoOld = EmployeeBuilder.Employee("Frodo")
          .withAge(40)
          .withPosition("Townsman")
          .withSalary(10_000)
          .withPrimaryAddress(new Address("Shire"))
          .withSkills("management")
          .withSubordinates(new Employee("Sam"))
          .build();

  Employee frodoNew = EmployeeBuilder.Employee("Frodo")
          .withAge(41)
          .withPosition("Hero")
          .withBoss(new Employee("Gandalf"))
          .withPrimaryAddress(new Address("Mordor"))
          .withSalary(12_000)
          .withSkills("management", "agile coaching")
          .withSubordinates(new Employee("Sméagol"), new Employee("Sam"))
          .build();

  //when
  Diff diff = javers.compare(frodoOld, frodoNew);

  //then
  assertThat(diff.getChanges()).hasSize(9);
}

javers.compare(frodoOld, frodoNew) берет два объекта, сравнивает их и сообщает о различиях. В вашем случае объект имеет список, и элементы в списках могут быть в другом порядке, в таком случае Javers сообщает о них как о разнице. Если вы хотите, чтобы порядок элементов игнорировался, то перед подачей Объектов в Javers вы можете отсортировать списки, а затем сравнить.

Вы можете взглянуть на Документация JaVers

Простейшим примером будет:

Person pOld = new Person ();
pOld.setName("Foo"):

Person pNew = new Person ();
pNew.setName("Bar"):

Diff diff = javers.compare(pOld, pNew);

diff.getChanges() выдаст список различий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...