Как сделать так, чтобы два разных списка массивов ссылались на один и тот же объект при анализе файла Json

#java #json #parsing

Вопрос:

Я пытаюсь проанализировать файл данных json, в котором есть отдельный объект внутри двух разных списков массивов:

 {  "TA": [  {  "firstname": "John",  "lastname": "Smith"  },  {  "firstname": "Jane",  "lastname": "Doe"  }  ],  "Student": [  {  "firstname": "John",  "lastname": "Smith"  },  {  "firstname": "Kevin",  "lastname": "White"  }  ] }  

Мой текущий метод синтаксического анализа просто создает новый объект Person для каждого из них и добавляет их к каждому объекту списка, но я хочу, чтобы мой объект Person John Smith был единственным объектом, на который ссылается как список «TA», так и список «Студент». Как я мог пойти на это?

Комментарии:

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

2. Ответ будет зависеть от используемой вами библиотеки JSON. Который из них?

3. Можете ли вы добавить код вашего текущего синтаксического анализа? Я думаю, что у @shmosel правильный подход к использованию карты (также можно использовать хэш-набор), но его пример специально для Джексона, который вы, по-видимому, не используете?

4. @magicmn Вам придется выполнить итерацию по набору, чтобы найти интернированное значение.

Ответ №1:

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

 class Person {  private static Maplt;Person, Persongt; cache = new HashMaplt;gt;();   @JsonCreator  public static Person create(  @JsonProperty("firstname") String firstname,  @JsonProperty("lastname") String lastname) {  Person person = new Person(firstname, lastname);  return cache.computeIfAbsent(person, Function.identity());  }   final String firstname;  final String lastname;   private Person(String firstname, String lastname) {  this.firstname = firstname;  this.lastname = lastname;  }   @Override  public boolean equals(Object o) {  return o instanceof Person  amp;amp; Objects.equals(((Person)o).firstname, this.firstname)  amp;amp; Objects.equals(((Person)o).lastname, this.lastname);  }   @Override  public int hashCode() {  return Objects.hash(this.firstname, this.lastname);  } }  

Комментарии:

1. Я думаю, что оба аргумента конструктора create предполагают добавление имен свойств следующим образом: public static Person create(@JsonProperty("firstname") String firstname, @JsonProperty("lastname") String lastname) {...} .

2. @LHCHIN Спасибо, я хотел это сделать. Хотя вы могли бы избежать этого с помощью ParameterNamesМодуля.

3. Поскольку вы используете HashMap, я думаю, что лучше выделить метод hashCode() вместо equals, так как HashMap будет использовать хэш-код для различения ключа карты.

4. @efmalik Справедливая точка зрения. Обновленный.

Ответ №2:

TA и список студентов-это два разных списка. Если вы определяете каждый список и заполняете их одним и тем же объектом (человеком), да, они будут указывать на один и тот же объект. Это объектно-ориентированный подход.

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

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

В вашем случае вам придется создать статический объект person для каждого варианта (имя, фамилия)