The code shown below does output:
[b]
[a, b]
However I would expect it to print two identical lines in the output.
import java.util.*;
public class Test{
static void test(String... abc) {
Set<String> s = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
s.addAll(Arrays.asList("a", "b"));
s.removeAll(Arrays.asList(abc));
System.out.println(s);
}
public static void main(String[] args) {
test("A");
test("A", "C");
}
}
The spec clearly states that removeAll
"Removes all this collection's elements that are also contained in the
specified collection."
So from my understanding current behavior is unpredictable . Please help me understand this
You only read documentation partly. You forgot one important paragraph from TreeSet:
Note that the ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equals if it is to correctly implement the Set interface. (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because the Set interface is defined in terms of the equals operation, but a TreeSet instance 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 behavior of a set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Set interface.
Now removeAll implementation comes from AbstractSet and utilizes equals method. According to your code you will have that "a".equals("A") is not true so that elements are not considered equal even if you provided a comparator which manages them when used in the TreeSet itself. If you try with a wrapper then the problem goes away:
import java.util.*;
import java.lang.*;
class Test
{
static class StringWrapper implements Comparable<StringWrapper>
{
public final String string;
public StringWrapper(String string)
{
this.string = string;
}
#Override public boolean equals(Object o)
{
return o instanceof StringWrapper &&
((StringWrapper)o).string.compareToIgnoreCase(string) == 0;
}
#Override public int compareTo(StringWrapper other) {
return string.compareToIgnoreCase(other.string);
}
#Override public String toString() { return string; }
}
static void test(StringWrapper... abc)
{
Set<StringWrapper> s = new TreeSet<>();
s.addAll(Arrays.asList(new StringWrapper("a"), new StringWrapper("b")));
s.removeAll(Arrays.asList(abc));
System.out.println(s);
}
public static void main(String[] args)
{
test(new StringWrapper("A"));
test(new StringWrapper("A"), new StringWrapper("C"));
}
}
This because you are now providing a consistent implementation between equals and compareTo of your object so you never have incoherent behavior between how the objects are added inside the sorted set and how all the abstract behavior of the set uses them.
This is true in general, a sort of rule of three for Java code: if you implement compareTo or equals or hashCode you should always implement all of them to avoid problems with standard collections (even if hashCode is less crucial unless you are using these objects in any hashed collection). This is specified many times around java documentation.
This is an inconsistency in the implementation of TreeSet<E>, bordering on the bug. The code will ignore custom comparator when the number of items in the collection that you pass to removeAll is greater than or equal to the number of items in the set.
The inconsistency is caused by a small optimization: if you look at the implementation of removeAll, which is inherited from AbstractSet, the optimization goes as follows:
public boolean removeAll(Collection<?> c) {
boolean modified = false;
if (size() > c.size()) {
for (Iterator<?> i = c.iterator(); i.hasNext(); )
modified |= remove(i.next());
} else {
for (Iterator<?> i = iterator(); i.hasNext(); ) {
if (c.contains(i.next())) {
i.remove();
modified = true;
}
}
}
return modified;
}
you can see that the behavior is different when c has fewer items than this set (top branch) vs. when it has as many or more items (bottom branch).
Top branch uses the comparator associated with this set, while the bottom branch uses equals for comparison c.contains(i.next()) - all in the same method!
You can demonstrate this behavior by adding a few extra elements to the original tree set:
s.addAll(Arrays.asList("x", "z", "a", "b"));
Now the output for both test cases becomes identical, because remove(i.next()) utilizes the comparator of the set.
The reason is because the comparator String.CASE_INSENSITIVE_ORDER you use is not consistent with equals.
As stated by TreeSet:
Note that the ordering maintained by a set (whether or not an explicit comparator is provided)
must be consistent with equals if it is to correctly implement the Set interface.
Consistency with equals as stated by Comparable:
The natural ordering for a class C is said to be consistent with equals if and only if
e1.compareTo(e2) == 0 has the same boolean value as e1.equals(e2)
for every e1 and e2 of class C.
And as an example for the case insensitive comparator you use:
"a".compareTo("A") == 0 => true
while
"a".equals("A") => false
Related
I have the following code which will sort the Employees's based on their experience.
I am adding 2 employees with different name and same experience. I am expecting that at the end set will have 2 employees, but I am getting only one.
I have also overridden equals and hashcode, Can any one tell me why I am getting only one employee in the set.
Test Class
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.junit.Test;
public class SetWithComparator {
#Test
public void testComparatorWithSet() {
Comparator<Employee> comparator =
(emp1, emp2) -> emp1.getYearOFExp().compareTo(emp2.getYearOFExp());
Set<Employee> empSet = new TreeSet<>(comparator);
Employee e1 = new Employee();
e1.setName("Employee-1");
e1.setYearOFExp(12f);
Employee e2 = new Employee();
e2.setName("Employee-2");
e2.setYearOFExp(12f);
empSet.add(e1);
empSet.add(e2);
}
}
Model Class
class Employee {
private String name;
private Float yearOFExp;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Float getYearOFExp() {
return yearOFExp;
}
public void setYearOFExp(Float yearOFExp) {
this.yearOFExp = yearOFExp;
}
#Override
public boolean equals(Object obj) {
if (obj instanceof Employee) {
Employee e = (Employee) obj;
return new EqualsBuilder().append(name, e.getName()).isEquals();
} else {
return false;
}
}
#Override
public int hashCode() {
return new HashCodeBuilder().append(name).toHashCode();
}
}
Because the comparator is not consistent with your equals method. Please check the documentation of Comparator.
The ordering imposed by a comparator c on a set of elements S is said
to be consistent with equals if and only if c.compare(e1, e2)==0 has
the same boolean value as e1.equals(e2) for every e1 and e2 in S.
Caution should be exercised when using a comparator capable of
imposing an ordering inconsistent with equals to order a sorted set
(or sorted map). Suppose a sorted set (or sorted map) with an explicit
comparator c is used with elements (or keys) drawn from a set S. If
the ordering imposed by c on S is inconsistent with equals, the sorted
set (or sorted map) will behave "strangely." In particular the sorted
set (or sorted map) will violate the general contract for set (or
map), which is defined in terms of equals.
The exact behavior that you experience is hinted in the docs of Comparable (although you use comparator):
For example, if one adds two keys a and b such that (!a.equals(b) &&
a.compareTo(b) == 0) to a sorted set that does not use an explicit
comparator, the second add operation returns false (and the size of
the sorted set does not increase) because a and b are equivalent from
the sorted set's perspective.
In your case: comparator.compare(e1, e2) is 0, e1.equals(e2) is false.
For a SortedSet, the Comparator determines what elements are the same and it won’t contain duplicates. If you don’t want to consider all employees with the same experience to be the same, you have to add a secondary ordering:
Comparator<Employee> comparator = Comparator.comparing(Employee::getYearOFExp)
.thenComparing(Employee::getName);
Note that you have to include all properties that make up the identity of an employee. In your example, there is only the name, however, in real life scenarios you would have more. On the other hand, if you have an ID, that determines the identity, you don’t need to check other properties and, in fact, shouldn’t, as most properties, including the name, can change. This also applies to the implementation of equals and hashCode.
In order to warn about false assumptions about what can be assumed to be granted, gender changes are a real life fact and even birthdays may turn out to be false and need a correction.
It's written in all decent java courses, that if you implement the Comparable interface, you should (in most cases) also override the equals method to match its behavior.
Unfortunately, in my current organization people try to convince me to do exactly the opposite. I am looking for the most convincing code example to show them all the evil that will happen.
I think you can beat them by showing the Comparable javadoc that says:
It is strongly recommended (though not required) that natural
orderings be consistent with equals. This is so because sorted sets
(and sorted maps) without explicit comparators behave "strangely" when
they are used with elements (or keys) whose natural ordering is
inconsistent with equals. In particular, such a sorted set (or sorted
map) violates the general contract for set (or map), which is defined
in terms of the equals method.
For example, if one adds two keys a and b such that (!a.equals(b) &&
a.compareTo(b) == 0) to a sorted set that does not use an explicit
comparator, the second add operation returns false (and the size of
the sorted set does not increase) because a and b are equivalent from
the sorted set's perspective.
So especially with SortedSet (and SortedMap) if the compareTo method returns 0, it assumes it as equal and doesn't add that element second time even the the equals method returns false, and causes confusion as specified in the SortedSet javadoc
Note that the ordering maintained by a sorted set (whether or not an
explicit comparator is provided) must be consistent with equals if the
sorted set is to correctly implement the Set interface. (See the
Comparable interface or Comparator interface for a precise definition
of consistent with equals.) This is so because the Set interface is
defined in terms of the equals operation, but a sorted set 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 sorted set, equal. The behavior of a sorted set is
well-defined even if its ordering is inconsistent with equals; it just
fails to obey the general contract of the Set interface.
If you don't override the equals method, it inherits its behaviour from the Object class.
This method returns true if and only if the specified object is not null and refers to the same instance.
Suppose the following class:
class VeryStupid implements Comparable
{
public int x;
#Override
public int compareTo(VeryStupid o)
{
if (o != null)
return (x - o.x);
else
return (1);
}
}
We create 2 instances:
VeryStupid one = new VeryStupid();
VeryStupid two = new VeryStupid();
one.x = 3;
two.x = 3;
The call to one.compareTo(two) returns 0 indicating the instances are equal but the call to one.equals(two) returns false indicating they're not equal.
This is inconsistent.
Consistency of compareTo and equals is not required but strongly recommended.
I'll give it a shot with this example:
private static class Foo implements Comparable<Foo> {
#Override
public boolean equals(Object _other) {
System.out.println("equals");
return super.equals(_other);
}
#Override
public int compareTo(Foo _other) {
System.out.println("compareTo");
return 0;
}
}
public static void main (String[] args) {
Foo a, b;
a = new Foo();
b = new Foo();
a.compareTo(b); // prints 'compareTo', returns 0 => equal
a.equals(b); // just prints 'equals', returns false => not equal
}
You can see that your (maybe very important and complicated) comparission code is ignored when you use the default equals-method.
the method int compareTo(T o) allow you know if the T o is (in some way) superior or inferior of this, so it allow you to order a list of T o.
In the scenario of int compareTo(T o) you have to do :
is o InstanceOfThis ? => true/false ;
is o EqualOfThis ? => true/false ;
is o SuperiorOfThis ? => true/false ;
is o InferiorOfThis ? true/false ;
So you see you have the equality test, and the best way to not implement the equality two times is to put it in the boolean equals(Object obj) method.
I'm following a tutorial to better understand Natural Ordering, using TreeSet and the Comparable interface.
The tutorial tells me that, to add non-primitive custom objects to Sets, I need to implement equals() and hashCode(). However, even without implementing these methods I'm able to compile and run the code (as below). I am using IntelliJ with Java 8.
Is overriding equals() and hashCode() absolutely necessary when working with TreeSets (SortedSet interface) and natural ordering?
class My_Person implements Comparable<My_Person>{
private String name;
public My_Person(String name) {
this.name = name;
}
public String toString() {
return name;
}
// #Override
// public boolean equals(Object o) {
// if (this == o)
// return true;
// if (o == null || getClass() != o.getClass())
// return false;
// My_Person my_person = (My_Person) o;
// return Objects.equals(name, my_person.name);
// }
//
// #Override
// public int hashCode() {
// return Objects.hash(name);
// }
#Override
public int compareTo(My_Person person) {
return name.compareTo(person.name);
}
}
public class NaturalOrdering {
public static void main(String[] args) {
List<My_Person> list = new ArrayList<>();
Set<My_Person> set = new TreeSet<>();
addElement(list);
addElement(set);
Collections.sort(list);
showElement(list);
System.out.println("\n");
showElement(set);
}
private static void addElement(Collection<My_Person> collection) {
collection.add(new My_Person("Joe"));
collection.add(new My_Person("Sue"));
collection.add(new My_Person("Juliet"));
collection.add(new My_Person("Clare"));
collection.add(new My_Person("Mike"));
}
private static void showElement(Collection<My_Person> collection) {
for(My_Person element: collection) {
System.out.println(element);
}
}
}
This depends on your requirements for equality. If you don't override equals and hashCode, two objects are defined as equal if and only if they are identical (i.e. the same object). If you need some other definition for equality you must override the methods.
It is not "absolutely necessary", but then you may get unexpected/wrong output if you don't do so. So if you don't override them, it may still work sometimes, but it may fail too. So just to be safe, better override it.
It will fail if you need to check equality. But if you are only concerned with sorting of the stored objects as per your own defined logic in compareTo method, then I think there is no need to override equals or hashcode.
Its not required by TreeSet or for that matter any Set. But Set is by nature collection of unique objects. For primitive types, Java has way to know whether two objects are same or not. For non-primitive user has to tell Java on how to know whether two objects are same or not and way is to override equals and hashcode methods which are invoked by Set#add method to determine the object being added already exists in the set or not. So if you need a functional unique objects in your Set, you should implement equals and hashcode methods. Hope this helps. This is a good read on the same topic.
You have the source code for TreeSet (and TreeMap which TreeSet uses under the hood). You can clearly see that TreeSet (and TreeMap) rely on compareTo() and not hashCode().
On the other hand, the HashSet (and HashMap which HashSet uses under the hood) does use hashCode() and equals(). No big surprise, considering that they are named HashSet and HashMap.
I have a TreeSet containing wrappers which store a Foo object at a certain position, defined like so:
class Wrapper implements Comparable<Wrapper> {
private final Foo foo;
private final Double position;
...
#Override boolean equals(Object o) {
...
if(o instanceof Wrapper)
return o.getFoo().equals(this.foo);
if(o instanceof Foo)
return o.equals(this.foo);
}
#Override public int compareTo(MarkerWithPosition o) {
return position.compareTo(o.getPosition());
}
}
NavigableSet<Wrapper> fooWrappers = new TreeSet<Wrapper>();
because I want my TreeSet to be ordered by position but searchable by foo. But when I perform these operations:
Foo foo = new Foo(bar);
Wrapper fooWrapper = new Wrapper(foo, 1.0);
fooWrappers.add(fooWrapper);
fooWrapper.equals(new Wrapper(new Foo(bar), 1.0));
fooWrapper.equals(new Foo(bar));
fooWrappers.contains(fooWrapper);
fooWrappers.contains(new Wrapper(foo, 1.0));
fooWrappers.contains(new Wrapper(new Foo(bar), 1.0));
fooWrappers.contains(new Wrapper(foo, 2.0));
fooWrappers.contains(foo);
I get:
true
true
true
true
true
false
Exception in thread "main" java.lang.ClassCastException: org.gridqtl.Marker cannot be cast to java.lang.Comparable
at java.util.TreeMap.getEntry(TreeMap.java:325)
at java.util.TreeMap.containsKey(TreeMap.java:209)
at java.util.TreeSet.contains(TreeSet.java:217)
when I expecting them all to return true, so it seems like TreeSet.contains is not using my equals method as the API suggests. Is there another method I need to overwrite?
TreeSet is a Set implementation that does indeed use compareTo, as explained in the javadoc - emphasis mine:
Note that the ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equals if it is to correctly implement the Set interface. (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because the Set interface is defined in terms of the equals operation, but a TreeSet instance 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 behavior of a set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Set interface.
TreeSet is an ordered set.
equals cannot give you ordering information, hence TreeSet has to use something else.
This 'something else' is Comparable interface, or its cousin Comparator interface.
Both interfaces provide an information about how to order 2 objects of a class.
Suppose I need TreeSet with elements sorted with some domain logic. By this logic it doesn't matter order of some elements that doesn't equal so compare method can return 0, but in this case I couldn't put them in TreeSet.
So, question: what disadvantages I'll have from code like this:
class Foo implements Comparable<Foo>{}
new TreeSet<Foo>(new Comparator<Foo>(){
#Override
public int compare(Foo o1, Foo o2) {
int res = o1.compareTo(o2);
if(res == 0 || !o1.equals(o2)){
return o1.hashCode() - o2.hashCode();
}
return res;
}
});
Update:
Ok. If it should always be a consistency between the methods equals(), hashcode() and compareTo(), as #S.P.Floyd - seanizer and others said.
If it would be better or even good if I'll remove Comparable interface and move this logic in Comparator (I can do it without broken encapsulation)? So it will be:
class Foo{}
new TreeSet<Foo>(new Comparator<Foo>(){
#Override
public int compare(Foo o1, Foo o2) {
//some logic start
if(strictliBigger(o1, o2)){ return 1;}
if(strictliBigger(o2, o1)){ return -1;}
//some logic end
if(res == 0 || !o1.equals(o2)){
return o1.hashCode() - o2.hashCode();
}
return res;
}
});
Update 2:
Would System.identityHashCode(x) be better than hashCode() if I don't need stable sort?
While this might work, it is far from being a best practice.
From the SortedSet docs:
Note that the ordering maintained by a sorted set (whether or not an explicit comparator is provided) must be consistent with equals if the sorted set is to correctly implement the Set interface. (See the Comparable interface or Comparator interface for a precise definition of consistent with equals.) This is so because the Set interface is defined in terms of the equals operation, but a sorted set 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 sorted set, equal. The behavior of a sorted set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Set interface.
For objects that implement Comparable, there should always be a consistency between the methods equals(), hashcode() and compareTo().
I'm afraid a SortedSet is just not what you want, nor will a Guava MultiSet be adequate (because it will not let you independently retrieve multiple equal items). I think what you need is a SortedList. There is no such beast that I know of (maybe in commons-collections, but those are a bit on the legacy side), so I implemented one for you using Guava's ForwardingList as a base class. In short: this List delegates almost everything to an ArrayList it uses internally, but it uses Collections.binarySearch() in it's add() method to find the right insertion position and it throws an UnsupportedOperationException on all optional methods of the List and ListIterator interfaces that add or set values at a given position.
The Constructors are identical to those of ArrayList, but for each of them there is also a second version with a custom Comparator. If you don't use a custom Comparator, your list elements need to implement Comparable or RuntimeExceptions will occur during sorting.
public class SortedArrayList<E> extends ForwardingList<E> implements
RandomAccess{
private final class ListIteratorImpl extends ForwardingListIterator<E>{
private final int start;
public ListIteratorImpl(final int start){
this.start = start;
}
#Override
public void set(E element){throw new UnsupportedOperationException();}
#Override
public void add(E element){throw new UnsupportedOperationException();}
#Override
protected ListIterator<E> delegate(){return inner.listIterator(start);};
}
private Comparator<? super E> comparator;
private List<E> inner;
public SortedArrayList(){this(null, null, null);}
#SuppressWarnings("unchecked")
private SortedArrayList(
final List<E> existing,
final Collection<? extends E> values,
final Comparator<? super E> comparator
){
this.comparator =
(Comparator<? super E>)
(comparator == null
? Ordering.natural()
: comparator );
inner = (
existing == null
? (values == null
? new ArrayList<E>(values)
: new ArrayList<E>()
)
: existing;
}
public SortedArrayList(final Collection<? extends E> c){
this(null, c, null);
}
public SortedArrayList(final Collection<? extends E> c,
final Comparator<? super E> comparator){
this(null, c, comparator);
}
public SortedArrayList(final Comparator<? super E> comparator){
this(null, null, comparator);
}
public SortedArrayList(final int initialCapacity){
this(new ArrayList<E>(initialCapacity), null, null);
}
public SortedArrayList(final int initialCapacity,
final Comparator<? super E> comparator){
this(new ArrayList<E>(initialCapacity), null, comparator);
}
#Override
public boolean add(final E e){
inner.add(
Math.abs(
Collections.binarySearch(inner, e, comparator)
) + 1,
e
);
return true;
}
#Override
public void add(int i, E e){throw new UnsupportedOperationException();}
#Override
public boolean addAll(final Collection<? extends E> collection){
return standardAddAll(collection);
}
#Override
public boolean addAll(int i,
Collection<? extends E> es){
throw new UnsupportedOperationException();
}
#Override
protected List<E> delegate(){ return inner; }
#Override
public List<E> subList(final int fromIndex, final int toIndex){
return new SortedArrayList<E>(
inner.subList(fromIndex, toIndex),
null,
comparator
);
}
#Override
public ListIterator<E> listIterator(){ return new ListIteratorImpl(0); }
#Override
public ListIterator<E> listIterator(final int index){
return new ListIteratorImpl(index);
}
#Override
public E set(int i, E e){ throw new UnsupportedOperationException(); }
}
Beware: even for two Foos f1,f2 with f1 != f2 you could get f1.hashCode() == f2.hashCode()! That means you won't get a stable sorting with your compare Method.
There is no rule in Java which says that the hash codes of two objects must be different just because they aren't equal (so o1.hashCode() - o2.hashCode() could return 0 in your case).
Also the behavior of equals() should be consistent with the results from compareTo(). This is not a must but if you can't maintain this, it suggests that your design has a big flaw.
I strongly suggest to look at the other fields of the objects and use some of those to extend your comparison so you get a value != 0 for objects were equals() == false.
hashcode() method doesn't guarantee any less than or greater than. compare() and equals() should yield the same meaning, but its not necessary, though.
As far as I can understand from your confusing code (no offence intended :)), you want to add duplicates to the TreeSet. For that reason you came up with this implementation. Here is the reason, you can't put them in the TreeSet, quoting from the docs,
The behavior of a set is well-defined
even if its ordering is inconsistent
with equals; it just fails to obey the
general contract of the Set interface.
So, you need to do something with yor equals() method, so it can never return true whats so ever. The best implementation would be,
public boolean equals(Object o) {
return false;
}
By the way, if I am right in my understanding, why not you use List instead and sort that.
Very interesting question.
As far as I understand your problem is duplicate elements.
I think that if o1.equals(o2) their hash codes might be equal too. It depends on the implementation of hashCode() in your Foo class. So, I'd suggest you to use System.identityHashCode(x) instead.
You have a Foo class wich is comparable but want to use a different sorting in a TreeSet<Foo> structure. Then your idea is the correct way to do it. Use that constructor to "overrule" the natural sorting of Foo.
If you have no specific expected ordering for any two given elements, but still want to consider them un-equal, then you have to return some specified ordering anyway.
As others have posted, hashCode() isn't a good candidate, because the hashCode() values of both elements can easily be equal. System.identityHashCode() might be a better choice, but still isn't perfect, as even identityHashCode() doesn't guarantee unique values either
The Guava arbitrary() Ordering implements a Comparator using System.identityHashCode().
Yes, as others said above, hashCode() is not secure to use here. But if you dont care about the ordering of objects that are equal in terms of o1.compareTo(o2) == 0, you could do something like:
public int compare(Foo o1, Foo o2) {
int res = o1.compareTo(o2);
if (res == 0 && !o1.equals(o2)) {
return -1;
}
return res;
}
int res = o1.compareTo(o2);
if(res == 0 || !o1.equals(o2)){
return o1.hashCode() - o2.hashCode();
}
Can be problematic, since if 2 objects are equal (i.e. in your res == 0) then these 2 objects return the same hashcode. Hashcodes are not unique for every object.
Edit #Stas, The System.identityHashCode(Object x); still won't help you. The reason is described on the javadoc:
Returns the same hash code for the
given object as would be returned by
the default method hashCode(),
whether or not the given object's
class overrides hashCode(). The hash
code for the null reference is zero.
There are a couple of problems here:
Hash codes are not generally unique, and in particular System.identityHashCode will not be unique on vaguely modern JVMs.
This is not a question of stability. We are sorting an array, but creating a tree structure. The hash code collisions will cause compare to return zero, which for TreeSet means one object wins and the other is discarded - it does not degrade to a linked-list (the clue is having "Set" in the name).
There is generally an integer overflow issue with subtracting one hash code from another. This means the comparison wont be transitive (i.e. it is broken). As luck would have it, on the Sun/Oracle implementation, System.identityHashCode always returns positive values. This means that extensive testing will probably not find this particular sort of bug.
I don't believe there is a good way to achieve this using TreeSet.
Two points may be relevant and these are that the return in one situation is shown as -1 and this depends if a negative value is permitted in the function parameter variable or in the relevant country of use, and also if the method you are using is permitted. There are standard data arranging methods like selector or selection sort and the paper description or code is usually available from a national authority if a copy is not in your workplace. Using comparisons like greater than or less than can speed up the code and avoids the use of a direct comparison for equality by implied dropthrough to later script or code.