Со всем обсуждением использования набора мне приходит в голову, что, возможно, проблема может быть переформулирована. Зачем вообще использовать набор? Если вы просто хотите проверить членство, и ваш список источников отсортирован, тогда выполните бинарный поиск объекта - это будет так же быстро (и, вероятно, быстрее), чем любое n-дерево, которое вы можете себе представить, и это не так сложно код.
Итак, представьте интерфейс OrderedListSet, который просто оборачивает подчиненный объект List. Пока компаратор, используемый для упорядочивания списка, также используется для двоичного поиска, это должно быть довольно простым.
Все операции Set начнутся с вызова getIndex (Object ob), затем в списке будет выполнено соответствующее действие.