лучший способ конвертировать java.util.HashSet в набор Clojure

Запросы Datomic возвращают java.util.HashSet в целях совместимости. Я хотел бы использовать функции clojure.set, такие как разница в наборах результатов запроса. В настоящее время я конвертирую набор результатов в набор Clojure, используя (set datomic_result). Есть ли альтернатива этому?


person m33lky    schedule 16.03.2017    source источник
comment
Что не так с (set datomic_result) подходом?   -  person OlegTheCat    schedule 16.03.2017
comment
Меня это сейчас устраивает. Наборы результатов могут быть потенциально большими, и я считаю, что в этом есть накладные расходы.   -  person m33lky    schedule 16.03.2017
comment
Вам нужно выполнить несколько операций над наборами результатов, сохранив неизменность? Если нет, и вы не против изменить возвращенные HashSets, вам лучше всего использовать операции Set java (removeAll для difference, addAll для объединения и т. д.). Для двух элементов 10e6 HashSets с 5e6 в результирующей разнице разница занимает 6 секунд для вычисления с использованием clojure.set/difference и около 1 секунды с использованием removeAll из Java.   -  person Josh    schedule 17.03.2017
comment
@Josh Просто поставь это как ответ. Я не думаю, что мне нужна неизменность. Работают ли функции Java с наборами кортежей так же хорошо, как функции Clojure, т.е. используя = в элементах кортежа?   -  person m33lky    schedule 17.03.2017


Ответы (1)


Я не рекомендую вам полагаться на тот факт, что возвращаемое значение является java.util.Set, что является деталью реализации (согласно Datomic документация, тип возвращаемого значения — java.util.Collection).

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

;; set difference
(into #{} (remove to-remove) query-result)
;; set intersection
(into #{} (filter to-keep) query-result)
;; set union
(into my-set query-result)

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

person Valentin Waeselynck    schedule 17.03.2017
comment
Разве вам не нужен набор, чтобы сделать удаление эффективным? - person m33lky; 17.03.2017
comment
Если правый набор мал, он действительно будет быстрее, чем полное сканирование. - person Valentin Waeselynck; 18.03.2017
comment
Я имею в виду O(n^2) по сравнению с O(n) производительностью при использовании коллекции по сравнению с набором. Но вы правы, я должен принять во внимание, что один из них может быть маленьким. - person m33lky; 18.03.2017
comment
Ни один из приведенных примеров не имеет сложности O(nm) — только O(n). В моем предыдущем комментарии признавалось, что вы можете получить O(m), используя тот факт, что возвращаемый результат является набором. - person Valentin Waeselynck; 19.03.2017
comment
Можете ли вы просветить меня, как он волшебным образом узнает, что элемент, содержащийся в query-result, не находится в коллекции to-remove? - person m33lky; 19.03.2017
comment
В случае O(m): перебирая to-remove и проверяя принадлежность множества к query-result - person Valentin Waeselynck; 20.03.2017