The sorting problem of TreeSet class

Source: Internet
Author: User
Tags comparable set set sorts time and date

TreeSet supports two sorts of sorting methods: natural sorting and custom sorting. TreeSet is naturally sorted by default.


1. Natural sorting


TreeSet invokes the CompareTo (Object obj) method of the collection element to compare the size relationship between elements, and then arranges the collection elements in ascending order, which is a natural sort. (The premise of comparison: two objects of the same type).

Java provides a comparable interface that defines a CompareTo (object obj) method that returns an integer value that the class implementing the interface must implement, and the object of the class that implements the interface can compare size. When an object calls the method to compare with another object, such as Obj1.comparto (OBJ2), if the method returns 0, the two objects are equal, and if a positive integer is returned, the OBJ1 is greater than obj2, and if the method returns a negative integer, Indicates that obj1 is less than obj2.

Java common classes implement the comparable interface and provide a standard for comparing sizes. Common classes for implementing the comparable interface:
    • BigDecimal, Bigineger, and all numeric corresponding wrapper classes: Compare the sizes of the values they correspond to.
    • Character: Compared by the Unicode value of the character.
    • The wrapper class instance that corresponds to Boolean:true is greater than false for the corresponding wrapper class instance.
    • String: Compares the Unicode values of the characters in the string.
    • Date, Time: Later, the date is greater than the previous time and date.

If you attempt to add an object to TreeSet, the object's class must implement the comparable interface.
The following procedure will cause an error:
Class ERR
{
}
public class Testtreeseterror
{
public static void Main (string[] args)
{
TreeSet ts = new TreeSet ();
Add two Err objects to the TreeSet collection
Ts.add (New ERR ());
Ts.add (New ERR ());
}
}

Description
The above program attempts to add 2 Err objects to the TreeSet collection, and when the first object is added, there is no element in TreeSet, so there is no problem; When the second Err object is added, TreeSet invokes the object's CompareTo (object obj) method is compared to other elements in the collection-if the corresponding class does not implement the comparable interface, a ClassCastException exception is thrown. The classcastexception exception is also thrown when attempting to remove the first element of an element from TreeSet.

When comparing objects with the CompareTo (object obj) method, you need to convert the object obj of the comparison to the same type, because only two instances of the same class can compare size. That is, the object that should be the same class is added to TreeSet, or a ClassCastException exception is thrown. For example, when adding a string object to TreeSet, this operation is completely normal. When you add a second Date object, TreeSet calls the object's CompareTo (Object obj) method to compare with other elements in the collection, and the program throws an exception at this point.
In practical programming, programmers can define their own classes to add multiple types of objects to treeset, provided that the user-defined class implements the comparable interface, which is implemented when the CompareTo (Object obj) method is implemented without forcing a type conversion. However, when you manipulate the collection data in TreeSet, the classcastexceptio exception will still occur for different types of elements. (read carefully and you will understand)

When an object is added to the TreeSet collection, TreeSet calls the object's CompareTo (Object obj) method to compare size with other objects in the container, and then determines where it is stored based on the red-black tree algorithm. If two objects are compared by CompareTo (object obj), TreeSet thinks they are stored in the same location.

For TreeSet collections, it is judged that two objects are not equal by two objects that return false by the Equals method, or by CompareTo (object obj) that does not return 0--even if two objects are the same object. TreeSet also treats them as two objects.
As shown in the following program:

Class Z, overriding the Equals method, always returning false,
Overriding the CompareTo (Object obj) method, always returning a positive integer
Class Z implements comparable
{
int age;
Public Z (Int.)
{
This.age = age;
}
public boolean equals (Object obj)
{
return false;
}
public int compareTo (Object obj)
{
return 1;
}
}
public class Testtreeset
{
public static void Main (string[] args)
{
TreeSet set = new TreeSet ();
Z z1 = new Z (6);
Set.add (z1);
System.out.println (Set.add (z1));
The output set set below will see 2 elements
SYSTEM.OUT.PRINTLN (set);
Modifies the age property of the first element of a set collection
((Z) (Set.first ())). Age = 9;
The Age property of the last element of the output set set will be seen as a 9
System.out.println (((Z) (Set.last ())).
}
}
Program Run Result:

True
[[Email protected], [email protected]]
9

Description
The same object was added two times in the program because the Equals () method of the Z1 object always returns False, and the CompareTo (object obj) method always returns 1. This way TreeSet will think that the Z1 object is not the same as itself, so add two Z1 objects to TreeSet. The two elements saved by the TreeSet object are actually the same element. So when you modify the age property of the first element in the TreeSet collection, the Age property of the last element in the TreeSet collection changes.

Summary: When you need to put an object into TreeSet, overriding the Equals () method of that object's corresponding class, you should ensure that the method has a consistent result with the CompareTo (object obj) method, and that the rule is: If two objects are returned true by the Equals method, These two objects should return 0 by comparing the CompareTo (Object obj) method.

If two objects return true through the Equals method, but the two objects are compared by the CompareTo (object obj) method to not return 0 o'clock, this will cause TreeSet to save the two objects in a different location, so that two objects can be added successfully. This is a bit out of the rules for set sets.

If two objects are compared by the CompareTo (object obj) method to return 0 o'clock, they are more cumbersome to return false by using the Equals method: Because two objects compare equality by CompareTo (object obj) method, TreeSet will try to keep them in the same place, but in fact it doesn't work (otherwise there will be only one object), so it's a bit cumbersome to deal with.

If you add a Mutable object to TreeSet, and the subsequent program modifies the properties of the Mutable object, causing it to change in size order with other objects, the TreeSet does not adjust their order again, and may even cause the two objects to be saved in TreeSet. They compare the return True,compareto (Object obj) method by the Equals method to return 0.
As shown in the following program:
Class R
{
int count;
public R (int count)
{
This.count = count;
}
Public String toString ()
{
Return "R (Count property:" + Count + ")";
}
public boolean equals (Object obj)
{
if (obj instanceof R)
{
R r = (r) obj;
if (R.count = = This.count)
{
return true;
}
}
return false;
}
public int hashcode ()
{
return this.count;
}
}
public class TestHashSet2
{
public static void Main (string[] args)
{
HashSet hs = new HashSet ();
Hs.add (New R (5));
Hs.add (New R (-3));
Hs.add (New R (9));
Hs.add (New R (-2));
Prints the TreeSet collection, where the collection elements are arranged in an orderly fashion
SYSTEM.OUT.PRINTLN (HS);
Take the first element out of the
Iterator it = Hs.iterator ();
R first = (R) it.next ();
Assign a value to the Count property of the first element
First.count =-3;
Output count again will see the elements in the TreeSet in an unordered state
SYSTEM.OUT.PRINTLN (HS);
Hs.remove (New R (-3));
SYSTEM.OUT.PRINTLN (HS);
Output false
SYSTEM.OUT.PRINTLN ("Does HS contain R objects with Count 3?") + Hs.contains (New R (-3)));
Output false
SYSTEM.OUT.PRINTLN ("Does HS contain a R object with Count 5?") "+ Hs.contains (new R (5)));
}
}

Program Run Result:

[R (Count property:-3), R (Count property:-2), R (Count property: 5), R (Count property: 9)]
[R (Count property:), R (Count property:-2), R (Count property: 5), R (Count property:-2)]
[R (Count property:), R (Count property:-2), R (Count property: 5), R (Count property:-2)]
[R (Count property:), R (Count property:-2), R (Count property:-2)]



Description
The R object in the above program is a normal override of the Equals method and the comparable method class, both of which use the Count property of the R object as the basis for judging. You can see that the results of the first output of the program are ordered in order. When you change the Count property of an R object, the output of the program changes, and it contains duplicate elements. Once you change the properties of a mutable element in the TreeSet collection, when the view deletes the object, TreeSet also deletes the failure (even if the collection is original, the attribute is not modified, but the element that is equal to the modified element cannot be deleted), so delete the count
When the R object is 2, no element is deleted, and the program can delete the R object with Count 5, which indicates that TreeSet can delete objects that are not modified and that are not duplicates of other modified properties.

Summary: With HashSet These objects will be very complex and error-prone. To make the program more robust, it is recommended that only immutable objects be placed in the HashSet and TreeSet collections.


2. Custom sorting


The natural sort of treeset is based on the size of the collection elements, treeset them in ascending order. If you need to implement custom sorting, such as descending, you can use the comparator interface. The interface contains an int compare (t O1, T O2) method, which is used to compare the sizes of O1 and O2.
If you need to implement custom sorting, you need to create a TreeSet collection object and provide an comparator object associated with the TreeSet collection, which is responsible for the sorting logic of the collection elements.
As shown in the following program:
Class M {
int age;
Public M (int age) {
This.age = age;
}
Public String toString () {
Return "M object (age:" + Age + ")";
}
}
public class TestTreeSet3 {
public static void Main (string[] args) {
TreeSet ts = new TreeSet (new Comparator () {
public int Compare (object O1, Object O2) {
M m1 = (m) O1;
M m2 = (m) O2;
if (M1.age > M2.age) {
return-1;
} else if (m1.age = = m2.age) {
return 0;
} else {
return 1;
}
}
});
Ts.add (New M (5));
Ts.add (New M (-3));
Ts.add (New M (9));
SYSTEM.OUT.PRINTLN (TS);
}
}
Program Run Result:

[M Object (Age:9), M object (Age:5), M object (age:-3)]

Description
The above program creates an anonymous inner class object for the comparator interface, which is responsible for sorting the TS collection. So when we add the M object to the TS collection, the M class is not required to implement the comparable interface, because at this point the TreeSet does not need to compare the size by the M object, but rather by the comparator object associated with the TreeSet, which is responsible for the ordering of the collection elements. When you use custom sorting, TreeSet sorts the collection elements regardless of the size of the collection elements themselves, but instead the comparator object is responsible for the collation of the collection elements.

The sorting problem of TreeSet class

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.