Переписывать нужно методы hashСode и equals вместе.
Получилось так, что equals, вызываемый при обнаружении равенства hasСode, унаследован от Object. А он там сравнивает объекты по их адресу в памяти. Которые, для разных объектов, само собой, разные. Поэтому Ваш HashSet и считает что ВСЕ новые объекты, какой бы ни был у них hashcode, будут разными!
Просто перепишите и equals, чтобы он сравнивал между собой соответствующие друг другу поля класса у разных его экземпляров. И при их равенстве HashSet отвергнет второй объект, у которого тот же hashCode и те же значения полей.
Больше про эти дела, например
тут.
И вообще это очень полезное и железное правило: одновременно менять (или проверять работоспособность этой сладкой парочки) hashCode и equals.