我在使用TreeSet时遇到了一些问题:为什么它会接受重复元素?我以为TreeSet通过比较器检测并自动删除重复元素。请帮帮我,我对Java和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);
}
}
编辑:以下是我实现hashCode和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();
}
编辑2:
这是更新后的Song类equals方法、toString和compareTo方法:
@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);
}
所以现在在SortedSongs中的Comparator
Comparator<Song> comp = (Song c1, Song c2)-> c1.compareTo(c2);
尽管如此,仍然不起作用,我觉得我可能漏掉了一些显而易见的东西。
编辑3: 问题已解决,实际上是我在测试类中犯了一个错误。很尴尬。抱歉,我没有想浪费你的时间,希望这对某人有所帮助。
toString
是如何实现的,并最好还要显示哪些“Song”对象最终成为重复项。通常,比较器必须与“equals”一致,以遵守“Set”接口的契约,但即使没有适当的“equals”实现,您也不应该看到重复项。 - Marco13equals
实现方式 不是 有效的。通常规则是:如果两个对象根据equals
方法相等,那么它们必须具有相同的hashCode
。但是如果它们具有相同的hashCode
,则它们不一定根据equals
方法相等。这只是一个附带说明,因为它对你正在观察的问题 应该 不相关。 - Marco13equals
和Comparator<Song>
还不太正确。先尝试修复它们,使它们可以逐个字段比较Song
。 - lexicore