TreeSet Comparator failed to remove duplicates in some cases?
up vote
0
down vote
favorite
I have the following comparator for my TreeSet:
public class Obj {
public int id;
public String value;
public Obj(int id, String value) {
this.id = id;
this.value = value;
}
public String toString() {
return "(" + id + value + ")";
}
}
Obj obja = new Obj(1, "a");
Obj objb = new Obj(1, "b");
Obj objc = new Obj(2, "c");
Obj objd = new Obj(2, "a");
Set<Obj> set = new TreeSet<>((a, b) -> {
System.out.println("Comparing " + a + " and " + b);
int result = a.value.compareTo(b.value);
if (a.id == b.id) {
return 0;
}
return result == 0 ? Integer.compare(a.id, b.id) : result;
});
set.addAll(Arrays.asList(obja, objb, objc, objd));
System.out.println(set);
It prints out [(1a), (2c)], which removed the duplicates.
But when I changed the last Integer.compare to Integer.compare(b.id, a.id) (i.e. switched the positions of a and b), it prints out [(2a), (1a), (2c)]. Clearly the same id 2 appeared twice.
How do you fix the comparator to always remove the duplicates based on ids and sort the ordered set based on value (ascending) then id (descending)?
java sorting comparator treeset
add a comment |
up vote
0
down vote
favorite
I have the following comparator for my TreeSet:
public class Obj {
public int id;
public String value;
public Obj(int id, String value) {
this.id = id;
this.value = value;
}
public String toString() {
return "(" + id + value + ")";
}
}
Obj obja = new Obj(1, "a");
Obj objb = new Obj(1, "b");
Obj objc = new Obj(2, "c");
Obj objd = new Obj(2, "a");
Set<Obj> set = new TreeSet<>((a, b) -> {
System.out.println("Comparing " + a + " and " + b);
int result = a.value.compareTo(b.value);
if (a.id == b.id) {
return 0;
}
return result == 0 ? Integer.compare(a.id, b.id) : result;
});
set.addAll(Arrays.asList(obja, objb, objc, objd));
System.out.println(set);
It prints out [(1a), (2c)], which removed the duplicates.
But when I changed the last Integer.compare to Integer.compare(b.id, a.id) (i.e. switched the positions of a and b), it prints out [(2a), (1a), (2c)]. Clearly the same id 2 appeared twice.
How do you fix the comparator to always remove the duplicates based on ids and sort the ordered set based on value (ascending) then id (descending)?
java sorting comparator treeset
What is your exact desired result in each case?
– Ole V.V.
16 hours ago
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
I have the following comparator for my TreeSet:
public class Obj {
public int id;
public String value;
public Obj(int id, String value) {
this.id = id;
this.value = value;
}
public String toString() {
return "(" + id + value + ")";
}
}
Obj obja = new Obj(1, "a");
Obj objb = new Obj(1, "b");
Obj objc = new Obj(2, "c");
Obj objd = new Obj(2, "a");
Set<Obj> set = new TreeSet<>((a, b) -> {
System.out.println("Comparing " + a + " and " + b);
int result = a.value.compareTo(b.value);
if (a.id == b.id) {
return 0;
}
return result == 0 ? Integer.compare(a.id, b.id) : result;
});
set.addAll(Arrays.asList(obja, objb, objc, objd));
System.out.println(set);
It prints out [(1a), (2c)], which removed the duplicates.
But when I changed the last Integer.compare to Integer.compare(b.id, a.id) (i.e. switched the positions of a and b), it prints out [(2a), (1a), (2c)]. Clearly the same id 2 appeared twice.
How do you fix the comparator to always remove the duplicates based on ids and sort the ordered set based on value (ascending) then id (descending)?
java sorting comparator treeset
I have the following comparator for my TreeSet:
public class Obj {
public int id;
public String value;
public Obj(int id, String value) {
this.id = id;
this.value = value;
}
public String toString() {
return "(" + id + value + ")";
}
}
Obj obja = new Obj(1, "a");
Obj objb = new Obj(1, "b");
Obj objc = new Obj(2, "c");
Obj objd = new Obj(2, "a");
Set<Obj> set = new TreeSet<>((a, b) -> {
System.out.println("Comparing " + a + " and " + b);
int result = a.value.compareTo(b.value);
if (a.id == b.id) {
return 0;
}
return result == 0 ? Integer.compare(a.id, b.id) : result;
});
set.addAll(Arrays.asList(obja, objb, objc, objd));
System.out.println(set);
It prints out [(1a), (2c)], which removed the duplicates.
But when I changed the last Integer.compare to Integer.compare(b.id, a.id) (i.e. switched the positions of a and b), it prints out [(2a), (1a), (2c)]. Clearly the same id 2 appeared twice.
How do you fix the comparator to always remove the duplicates based on ids and sort the ordered set based on value (ascending) then id (descending)?
java sorting comparator treeset
java sorting comparator treeset
asked 17 hours ago
user1589188
1,55782764
1,55782764
What is your exact desired result in each case?
– Ole V.V.
16 hours ago
add a comment |
What is your exact desired result in each case?
– Ole V.V.
16 hours ago
What is your exact desired result in each case?
– Ole V.V.
16 hours ago
What is your exact desired result in each case?
– Ole V.V.
16 hours ago
add a comment |
1 Answer
1
active
oldest
votes
up vote
0
down vote
You're askimg:
How do you fix the comparator to always remove the duplicates based on ids and sort the ordered set based on value (ascending) then id (descending)?
You want the comparator to
- remove duplicates based on
Obj.id
- sort the set by
Obj.alueandObj.id
Requirement 1) results in
Function<Obj, Integer> byId = o -> o.id;
Set<Obj> setById = new TreeSet<>(Comparator.comparing(byId));
Requirement 2) results in
Function<Obj, String> byValue = o -> o.value;
Comparator<Obj> sortingComparator = Comparator.comparing(byValue).thenComparing(Comparator.comparing(byId).reversed());
Set<Obj> setByValueAndId = new TreeSet<>(sortingComparator);
Let's have a look on the JavaDoc of TreeSet. It says:
Note that the ordering maintained by a set [...] must be consistent with
equalsif it is to
correctly implement theSetinterface. This is so
because theSetinterface is defined in terms of theequalsoperation,
but aTreeSetinstance performs all element comparisons using its
compareTo(or compare) method, so two elements that are deemed equal
by this method are, from the standpoint of the set, equal.
The set will be ordered according to the comparator but its elements are also compared for equality using the comparator.
As far as I can see there is no way to define a Comparator which satisfies both requirements. Since a TreeSet is in the first place a Set requirement 1) has to match. To achieve requirement 2) you can create a second TreeSet:
Set<Obj> setByValueAndId = new TreeSet<>(sortingComparator);
setByValueAndId.addAll(setById);
Or if you don't need the set itself but to process the elements in the desired order you can use a Stream:
Consumer<Obj> consumer = <your consumer>;
setById.stream().sorted(sortingComparator).forEach(consumer);
BTW:
While it's possible to sort the elements of a Stream according to a given Comparator there is no distinct method taking a Comparator to remove duplicates according to it.
Thanks. Thats why I chose TreeSet to do both the custom distinct and sorting. But I don't understand how it is impossible to achieve what I want? The equality part is done in my comparator, hence the returning of 0 for duplicates removal. Only after that there goes the sorting logic (i.e. not duplicates).
– user1589188
2 hours ago
add a comment |
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
0
down vote
You're askimg:
How do you fix the comparator to always remove the duplicates based on ids and sort the ordered set based on value (ascending) then id (descending)?
You want the comparator to
- remove duplicates based on
Obj.id
- sort the set by
Obj.alueandObj.id
Requirement 1) results in
Function<Obj, Integer> byId = o -> o.id;
Set<Obj> setById = new TreeSet<>(Comparator.comparing(byId));
Requirement 2) results in
Function<Obj, String> byValue = o -> o.value;
Comparator<Obj> sortingComparator = Comparator.comparing(byValue).thenComparing(Comparator.comparing(byId).reversed());
Set<Obj> setByValueAndId = new TreeSet<>(sortingComparator);
Let's have a look on the JavaDoc of TreeSet. It says:
Note that the ordering maintained by a set [...] must be consistent with
equalsif it is to
correctly implement theSetinterface. This is so
because theSetinterface is defined in terms of theequalsoperation,
but aTreeSetinstance performs all element comparisons using its
compareTo(or compare) method, so two elements that are deemed equal
by this method are, from the standpoint of the set, equal.
The set will be ordered according to the comparator but its elements are also compared for equality using the comparator.
As far as I can see there is no way to define a Comparator which satisfies both requirements. Since a TreeSet is in the first place a Set requirement 1) has to match. To achieve requirement 2) you can create a second TreeSet:
Set<Obj> setByValueAndId = new TreeSet<>(sortingComparator);
setByValueAndId.addAll(setById);
Or if you don't need the set itself but to process the elements in the desired order you can use a Stream:
Consumer<Obj> consumer = <your consumer>;
setById.stream().sorted(sortingComparator).forEach(consumer);
BTW:
While it's possible to sort the elements of a Stream according to a given Comparator there is no distinct method taking a Comparator to remove duplicates according to it.
Thanks. Thats why I chose TreeSet to do both the custom distinct and sorting. But I don't understand how it is impossible to achieve what I want? The equality part is done in my comparator, hence the returning of 0 for duplicates removal. Only after that there goes the sorting logic (i.e. not duplicates).
– user1589188
2 hours ago
add a comment |
up vote
0
down vote
You're askimg:
How do you fix the comparator to always remove the duplicates based on ids and sort the ordered set based on value (ascending) then id (descending)?
You want the comparator to
- remove duplicates based on
Obj.id
- sort the set by
Obj.alueandObj.id
Requirement 1) results in
Function<Obj, Integer> byId = o -> o.id;
Set<Obj> setById = new TreeSet<>(Comparator.comparing(byId));
Requirement 2) results in
Function<Obj, String> byValue = o -> o.value;
Comparator<Obj> sortingComparator = Comparator.comparing(byValue).thenComparing(Comparator.comparing(byId).reversed());
Set<Obj> setByValueAndId = new TreeSet<>(sortingComparator);
Let's have a look on the JavaDoc of TreeSet. It says:
Note that the ordering maintained by a set [...] must be consistent with
equalsif it is to
correctly implement theSetinterface. This is so
because theSetinterface is defined in terms of theequalsoperation,
but aTreeSetinstance performs all element comparisons using its
compareTo(or compare) method, so two elements that are deemed equal
by this method are, from the standpoint of the set, equal.
The set will be ordered according to the comparator but its elements are also compared for equality using the comparator.
As far as I can see there is no way to define a Comparator which satisfies both requirements. Since a TreeSet is in the first place a Set requirement 1) has to match. To achieve requirement 2) you can create a second TreeSet:
Set<Obj> setByValueAndId = new TreeSet<>(sortingComparator);
setByValueAndId.addAll(setById);
Or if you don't need the set itself but to process the elements in the desired order you can use a Stream:
Consumer<Obj> consumer = <your consumer>;
setById.stream().sorted(sortingComparator).forEach(consumer);
BTW:
While it's possible to sort the elements of a Stream according to a given Comparator there is no distinct method taking a Comparator to remove duplicates according to it.
Thanks. Thats why I chose TreeSet to do both the custom distinct and sorting. But I don't understand how it is impossible to achieve what I want? The equality part is done in my comparator, hence the returning of 0 for duplicates removal. Only after that there goes the sorting logic (i.e. not duplicates).
– user1589188
2 hours ago
add a comment |
up vote
0
down vote
up vote
0
down vote
You're askimg:
How do you fix the comparator to always remove the duplicates based on ids and sort the ordered set based on value (ascending) then id (descending)?
You want the comparator to
- remove duplicates based on
Obj.id
- sort the set by
Obj.alueandObj.id
Requirement 1) results in
Function<Obj, Integer> byId = o -> o.id;
Set<Obj> setById = new TreeSet<>(Comparator.comparing(byId));
Requirement 2) results in
Function<Obj, String> byValue = o -> o.value;
Comparator<Obj> sortingComparator = Comparator.comparing(byValue).thenComparing(Comparator.comparing(byId).reversed());
Set<Obj> setByValueAndId = new TreeSet<>(sortingComparator);
Let's have a look on the JavaDoc of TreeSet. It says:
Note that the ordering maintained by a set [...] must be consistent with
equalsif it is to
correctly implement theSetinterface. This is so
because theSetinterface is defined in terms of theequalsoperation,
but aTreeSetinstance performs all element comparisons using its
compareTo(or compare) method, so two elements that are deemed equal
by this method are, from the standpoint of the set, equal.
The set will be ordered according to the comparator but its elements are also compared for equality using the comparator.
As far as I can see there is no way to define a Comparator which satisfies both requirements. Since a TreeSet is in the first place a Set requirement 1) has to match. To achieve requirement 2) you can create a second TreeSet:
Set<Obj> setByValueAndId = new TreeSet<>(sortingComparator);
setByValueAndId.addAll(setById);
Or if you don't need the set itself but to process the elements in the desired order you can use a Stream:
Consumer<Obj> consumer = <your consumer>;
setById.stream().sorted(sortingComparator).forEach(consumer);
BTW:
While it's possible to sort the elements of a Stream according to a given Comparator there is no distinct method taking a Comparator to remove duplicates according to it.
You're askimg:
How do you fix the comparator to always remove the duplicates based on ids and sort the ordered set based on value (ascending) then id (descending)?
You want the comparator to
- remove duplicates based on
Obj.id
- sort the set by
Obj.alueandObj.id
Requirement 1) results in
Function<Obj, Integer> byId = o -> o.id;
Set<Obj> setById = new TreeSet<>(Comparator.comparing(byId));
Requirement 2) results in
Function<Obj, String> byValue = o -> o.value;
Comparator<Obj> sortingComparator = Comparator.comparing(byValue).thenComparing(Comparator.comparing(byId).reversed());
Set<Obj> setByValueAndId = new TreeSet<>(sortingComparator);
Let's have a look on the JavaDoc of TreeSet. It says:
Note that the ordering maintained by a set [...] must be consistent with
equalsif it is to
correctly implement theSetinterface. This is so
because theSetinterface is defined in terms of theequalsoperation,
but aTreeSetinstance performs all element comparisons using its
compareTo(or compare) method, so two elements that are deemed equal
by this method are, from the standpoint of the set, equal.
The set will be ordered according to the comparator but its elements are also compared for equality using the comparator.
As far as I can see there is no way to define a Comparator which satisfies both requirements. Since a TreeSet is in the first place a Set requirement 1) has to match. To achieve requirement 2) you can create a second TreeSet:
Set<Obj> setByValueAndId = new TreeSet<>(sortingComparator);
setByValueAndId.addAll(setById);
Or if you don't need the set itself but to process the elements in the desired order you can use a Stream:
Consumer<Obj> consumer = <your consumer>;
setById.stream().sorted(sortingComparator).forEach(consumer);
BTW:
While it's possible to sort the elements of a Stream according to a given Comparator there is no distinct method taking a Comparator to remove duplicates according to it.
edited 12 hours ago
answered 12 hours ago
LuCio
2,4491722
2,4491722
Thanks. Thats why I chose TreeSet to do both the custom distinct and sorting. But I don't understand how it is impossible to achieve what I want? The equality part is done in my comparator, hence the returning of 0 for duplicates removal. Only after that there goes the sorting logic (i.e. not duplicates).
– user1589188
2 hours ago
add a comment |
Thanks. Thats why I chose TreeSet to do both the custom distinct and sorting. But I don't understand how it is impossible to achieve what I want? The equality part is done in my comparator, hence the returning of 0 for duplicates removal. Only after that there goes the sorting logic (i.e. not duplicates).
– user1589188
2 hours ago
Thanks. Thats why I chose TreeSet to do both the custom distinct and sorting. But I don't understand how it is impossible to achieve what I want? The equality part is done in my comparator, hence the returning of 0 for duplicates removal. Only after that there goes the sorting logic (i.e. not duplicates).
– user1589188
2 hours ago
Thanks. Thats why I chose TreeSet to do both the custom distinct and sorting. But I don't understand how it is impossible to achieve what I want? The equality part is done in my comparator, hence the returning of 0 for duplicates removal. Only after that there goes the sorting logic (i.e. not duplicates).
– user1589188
2 hours ago
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53371148%2ftreeset-comparator-failed-to-remove-duplicates-in-some-cases%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
What is your exact desired result in each case?
– Ole V.V.
16 hours ago