Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - TreeSet accepting duplicates

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.

like image 216
M. P. Avatar asked May 02 '18 23:05

M. P.


1 Answers

TreeSet is implemented with a balanced binary tree in Java (actually RedBlack tree) . So it does not use the equals method. It uses the Comparator.

Now the problem about your implementation is about your comparator. Your comparator is based on the toString method. By default java returns the name of the object's class plus its hash code. So by default the output of toString will be the same for two objects if and only if they are pointing to the same memory reference. You need to make sure that you have override the toString method in your class as you comparator is based on that.

To resolve the issue, you need to define a comparator that reflect the comparison logic of your program.

like image 161
MigSena Avatar answered Sep 25 '22 14:09

MigSena