Избегайте цикла и попытайтесь использовать API-интерфейсы для сбора (производительность) - PullRequest
2 голосов
/ 17 октября 2011

У меня есть кусок кода из старого проекта.

Логика (на высоком уровне) следующая:
Пользователь отправляет серию {id,Xi}, где id - это первичный ключ объекта в базе данных.
Цель состоит в том, чтобыбаза данных обновлена, но серия значений Xi всегда уникальна .

Т.е. если пользователь отправляет {1,X1} и в базе данных у нас есть {1,X2},{2,X1}, то ввод должен быть отклонен, в противном случае мы получим дубликаты, т.е. {1,X1},{2,X1}, т.е. у нас будет X1 дважды в разных строках.

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

В настоящее время реализация для этого использует "грубую силу", то есть непрерывные циклы for для ввода и набор результатов jdbc для обеспечения уникальности.

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

Я ищу лучший подход, как с точки зрения кодирования, так и производительности.

Я думал следующее:

  • Создайте Set из списка ввода пользователя.Если Set имеет другой размер, чем список, то ввод пользователя имеет дубликаты. Стоп там.
  • Загрузка данных из jdbc.
  • Создать HashMap<Long,String> с помощью ввода пользователя.Ключ является первичным ключом.
  • Зацикливание набора результатов.Если HashMap не contain ключ с тем же значением, что и идентификатор строки ResultSet, то добавьте его к HashMap
  • В конце получите значения HashMap как List. Если этосодержит дубликаты отклонения ввода.

Это алгоритм, который я придумал.
Есть ли лучший подход, чем этот?(Я предполагаю, что я не ошибаюсь в самом алгоритме)

Ответы [ 3 ]

3 голосов
/ 17 октября 2011

Чисто с точки зрения производительности, почему бы не позволить базе данных выяснить, есть ли дубликаты (например, {1,X1},{2,X1})?Имейте в таблице уникальное ограничение, а затем, когда оператор update завершится неудачно, выдав исключение, перехватите его и разберитесь с тем, что вы хотели бы сделать в этих условиях ввода.Вы также можете запустить это как одну транзакцию, просто если вам нужно откатить какие-либо частичные обновления.Конечно, это предполагает, что у вас нет каких-либо других бизнес-правил, управляющих обновлениями, которые вы не упомянули здесь.

С вашим алгоритмом вы тратите слишком много времени на итерации по HashMap с и List с, чтобы удалитьдублирует ИМХО.

1 голос
/ 18 октября 2011

Я бы выбрал решение на стороне базы данных. Предполагая таблицу со столбцами id и value, вы должны составить список со всеми «значениями» и использовать следующий SQL:

select count(*) from tbl where value in (:values);

привязка параметра :values к списку значений, однако, подходит для вашей среды. (Тривиально при использовании Spring JDBC и базы данных, которая поддерживает оператор in, меньше для небольших установок. В качестве последнего средства вы можете генерировать SQL динамически.) Вы получите набор результатов с одной строкой и одним столбцом числового значения тип. Если это 0, вы можете вставить новые данные; если это 1, сообщить о нарушении ограничения. (Если это что-то еще, у вас есть совершенно новая проблема.)

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

select value from tbl where value in (:values)

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

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

1 голос
/ 17 октября 2011

Поскольку вы не можете изменить базу данных, как указано в комментариях.Я, вероятно, расширил бы вашу идею Set.Создайте HashMap<Long, String> и поместите в него все элементы из базы данных, а затем создайте HashSet<String> со всеми значениями из вашей базы данных.

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

Если они не совпадают, то проверьте значение по HashSet, чтобы увидеть, существует ли оно уже.Если это так, то у вас есть дубликат.

Должен работать намного лучше, чем цикл.

Редактировать:

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

Возможно, есть лучший способ сделать это, но это лучшее, что я получил.

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