I'm having some problems with TreeSet: why does this one accept duplicates? I thought TreeSets detected them through the Comparator, and automatically remove them. Please help me, I'm kind of new to both Java and StackOverflow.
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
public class SortedSongs
{
private Set songs;
public SortedSongs()
{
Comparator<Song> comp = (Song c1, Song c2)-> c1.toString().compareTo(c2.toString());
songs = new TreeSet<>(comp);
}
}
edit: this is how I implemented hashCode and equals:
@Override
public int hashCode()
{
return Objects.hash(name, author);
}
@Override
public boolean equals(Object o)
{
return o == null ? false : o.getClass() != getClass() ? false
: o.hashCode() == hashCode();
}
edit2: This is the updated equals method, toString and compareTo for class Song
@Override
public boolean equals(Object o)
{
if (this==o) return true;
if (getClass()!=o.getClass()) return false;
return name.equals(((Song) o).name) && author.equals(((Song) o).author);
}
@Override
public String toString() {return name + " - " + author;}
public int compareTo(Song other)
{
if (name.equals(other.name))
return author.equals(other.author) ? 0 : author.compareTo(other.author);
return name.compareTo(other.name);
}
So now the Comparator in SortedSongs
Comparator<Song> comp = (Song c1, Song c2)-> c1.compareTo(c2);
Still not working though, I feel as if I'm missing something obvious
edit3: Solved, I actually made a mistake with my Test class. Embarrassing. Sorry, didn't mean to waste your time, I hope this will be helpful to someone.
toString
is implemented, and preferably also show whichSong
objects end up as duplicates. In general, the comparator has to be consistent with equals to obey the contract of theSet
interface, but even without a properequals
implementation, you should not see duplicates. – Riskyequals
implementation is not valid. The general rule is: If objects are equal according to theequals
method, then they must have the samehashCode
. But if they have the samehashCode
, then they are not necessarily equal according to theequals
method. Only a side note, because it should not be relevant for the issue that you are observing) – Riskyequals
andComparator<Song>
are not quite correct. Try to fix them first so that they compareSong
s field by field. – ForegoingtoString()
in classSong
– Wraparoundname
andauthor
? Also, can you give an example of some input that is causing it to fail? – Secundines