简体   繁体   中英

How to sort and avoid duplicates in TreeSet with my comparator?

I wan to create TreeSet() that will sort my elements with my predefined comparator. But the problem is when I give the comparator as a parameter to the constructor of the TreeSet(MyComparator) , the TreeSet is not avoiding duplicates. Can I achieve sorting of the elements and avoiding duplicates?

The comparator looks like:

public static Comparator<Participant> byNameAndAge = (L, R) -> {
    //check if they have the same code
    if (L.code.equalsIgnoreCase(R.code))
        return 0;

    int res = L.name.compareToIgnoreCase(R.name);
    if (res == 0)
        res = Integer.compare(L.age, R.age);
    return res;
};

You've misunderstood a few things. TreeSet does eliminate duplicates, with 'a duplicate' defined as 'any two elements for which your compare method returns 0'. No 2 such elements can both exist in a treeset. I'm sure your code doesn't work if you say so, but the code you pasted isn't the problem, nor is TreeSet's code.

A trivial example:

Comparator<String> byLength = (a, b) -> a.length() - b.length();
Set<String> set = new TreeSet<String>(byLength);
set.add("Hello");
set.add("World");
set.add("X");
set.add("VeryLong");
System.out.println(set);

> [X, Hello, VeryLong]

Note how 'World' disappeared, because the comparator says it is equal to Hello (they are both 5 length, a.length() - b.length() is returning 0, and 0 is 'equal, thus, eliminate the duplicate' according to treeset). In other words, your code as pasted would eliminate duplicates, the problem lies elsewhere.

This code is almost the same as yours.


Comparators chaining

public static void main(String[] args) {
    // custom comparator
    Comparator<Participant> byNameAndAge = Comparator
            // first sorting by name ignoring case
            .comparing(Participant::getName, String::compareToIgnoreCase)
            // second sorting by age
            .thenComparingInt(Participant::getAge);

    // constructor with a comparator as a parameter
    TreeSet<Participant> treeSet = new TreeSet<>(byNameAndAge);
    treeSet.addAll(Set.of( // test data
            new Participant("John", 25),
            new Participant("Junior", 2),
            new Participant("james", 31),
            new Participant("john", 22)));

    // output
    treeSet.forEach(System.out::println);
    //name=james, age=31
    //name=john, age=22
    //name=John, age=25
    //name=Junior, age=2
}
static class Participant {
    String name;
    int age;

    public Participant(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() { return name; }
    public int getAge() { return age; }

    @Override
    public String toString() {
        return "name=" + name + ", age=" + age;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM