Сравнение содержимого карты Java

Вот сложная структура данных и случай организации данных.

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

Каждый объект в настоящее время хранится в одной структуре данных HashMap<String, Object>. Каждый такой HashMap соответствует одной категории (группе). Каждая запись базы данных строится из информации всех объектов, содержащихся во всех категориях (структуры данных HashMap).

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

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

Идея состоит в том, чтобы просто отсортировать ключи (например, заменив каждый HashMap на TreeMap), а затем пройтись по всем картам. Альтернативой было бы просто скопировать все в TreeMap только для сравнения.

Каким будет наиболее эффективный способ реализации этой функции?

Кроме того, как бы вы нашли разницу (то есть добавленные и удаленные поля) между последовательными записями?


person PNS    schedule 28.04.2012    source источник


Ответы (2)


Создайте мета SortedSet, в котором вы будете хранить все созданные карты.

Означает SortedSet<Map<String,Object>> например. TreeSet, который как пользовательский Comparator<Map<String,Object>> точно проверяет ваши требования к тому же количеству и именам ключей и тому же типу объекта для каждого значения.

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

==== РЕДАКТИРОВАТЬ ====

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

Тем не менее, я бы использовал упомянутый SortedSet<Map<String,Object>>, но, конечно, Map<String,Object> теперь будет указывать на ту карту, которую вы и havexy предложили.

С другой стороны, может ли быть шагом вперед использование Set<Set<KeyAndType>> или SortedSet<Set<KeyAndType>>, где ваш KeyAndType будет содержать только ключ и тип с соответствующей реализацией Comparable или equals with hashcode.

Почему? Вы спрашивали, как найти различия между двумя записями? Если каждая запись относится к одному из этих внутренних Set<KeyAndType>, вы можете легко использовать retainAll() для формирования пересечения двух последовательных наборов.

Если бы вы сравнили это с идеей SortedSet<Map<String,Object>>, в обоих случаях у вас была бы логика, которая различает поля внутри компаратора, один раз сравнивая внутренние наборы, один раз сравнивая внутренние карты. А поскольку эта информация теряется при построении окружающего множества, впоследствии будет сложно получить различия между двумя записями, если у вас нет другой редуцированной структуры, которую легко использовать для поиска таких различий. И поскольку такой Set<KeyAndType> может выступать в качестве ключа, а также простой базы для сравнения двух записей, он может быть хорошим кандидатом для использования в обеих целях.

Если, кроме того, вы хотите сохранить связь между таким Set<KeyAndType> и вашей записью или группой Map<String,Object>, ваша метаструктура может быть примерно такой: Map<Set<KeyAndType>,DatabaseRecord> или Map<Set<KeyAndType>,GroupOfMaps> реализована простым LinkedHashMap, что позволяет выполнять простые итерации в исходном порядке.

person Omnaest    schedule 28.04.2012
comment
Итак, вы имеете в виду, что я должен создать собственный TreeSet, который реализует Comparator‹Map‹String, Object››? Это отсортирует объекты Map‹String, Object›, но как будет отсортировано их содержимое? - person PNS; 29.04.2012
comment
@PNS Прочитав ваше описание во второй раз, я больше не уверен, правильно ли я его понимаю. Вы читаете такие типы, как String, Boolean, Integer из файла. Позже вы расскажете о столбцах в сочетании записей. У примитивов такого нет, поэтому я предположил, что запись будет переведена в одну из тех карт, о которых вы говорите, поскольку ключи = столбцы. Но, возможно, вы можете сначала прокомментировать это, чтобы прояснить это? - person Omnaest; 29.04.2012
comment
Вы почти правы. Запись — это объединение всех карт, а ключи — это имена столбцов. - person PNS; 30.04.2012

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

Поэтому всякий раз, когда вы добавляете/удаляете в HashMap, вы будете выполнять ту же операцию и в TreeMap. Таким образом, оба всегда будут синхронизированы.

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

person havexz    schedule 28.04.2012