Java - 接受重复的TreeSet

M. *_* P. 6 java comparator treeset

我在使用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:这是我实现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();
}
Run Code Online (Sandbox Code Playgroud)

edit2:这是类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);
}
Run Code Online (Sandbox Code Playgroud)

所以现在是SortedSongs中的比较器

Comparator<Song> comp = (Song c1, Song c2)-> c1.compareTo(c2);
Run Code Online (Sandbox Code Playgroud)

虽然还没有工作,但我觉得好像缺少了一些明显的东西

edit3:解决了,我的Test类实际上犯了一个错误.尴尬.对不起,不是浪费你的时间,我希望这会对某人有所帮助.

小智 5

TreeSet是用Java中的平衡二叉树(实际上是红黑树)实现的。所以它不使用该equals方法。它使用Comparator.

现在关于你的实现的问题是关于你的comparator. 您的比较器基于该toString方法。默认情况下,java 返回对象类的名称及其哈希码。因此,默认情况下,toString当且仅当两个对象指向相同的内存引用时,它们的输出才会相同。您需要确保toString在类中覆盖了该方法,因为您的比较器基于该方法。

要解决此问题,您需要定义一个比较器来反映程序的比较逻辑。