【发布时间】:2018-05-02 23:14:43
【问题描述】:
我在使用 TreeSet 时遇到了一些问题:为什么这个接受重复项?我认为 TreeSets 通过比较器检测到它们,并自动删除它们。请帮助我,我对 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<Song> comp = (Song c1, Song c2)-> c1.compareTo(c2);
仍然无法正常工作,我觉得好像我错过了一些明显的东西
编辑3: 解决了,我实际上在我的测试课上犯了一个错误。尴尬。抱歉,不是故意浪费您的时间,希望这对某人有所帮助。
【问题讨论】:
-
他们使用哈希码和等号来查看是否在集合中。
-
问题可能有点微妙:您正在通过字符串表示来比较歌曲。您应该向我们展示
toString是如何实现的,并且最好还展示哪些Song对象最终会重复。一般来说,比较器必须与equals一致以遵守Set接口的约定,但即使没有正确的equals实现,您也不应该看到重复。 -
(附注:您当前的
equals实现是not 有效的。一般规则是:If 对象根据equals方法,那么它们必须具有相同的hashCode。但是如果它们具有相同的hashCode,那么根据@987654333,它们不一定相等@ 方法。只是一个旁注,因为它应该与您正在观察的问题无关) -
您的
equals和Comparator<Song>不太正确。尝试先修复它们,以便它们逐个字段比较Songs。 -
equals方法是绝对错误的。 Joshua Bloch 在“Effective Java”的第 3 章中告诉您如何正确覆盖 equals 和 hashCode。
标签: java comparator treeset