This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Java sort problem by two fields
I have user object like
class user
{
String firstName;
String lastName;
}
I have a List which contains these object , I have to sort it by first name and if first name matches the sort only those name by last name .
There are a couple of approaches here.
You can to implement a Comparator, and then use this in the standard Java Collection lib to sort your collection e.g. Collections.sort()
Comparator<MyObject> comparator = ....
Collections.sort(listOfObjects, comparator); // note- will sort in place
An alternative is for your object to implement Comparable. This then introduces a native sort order to your object.
Note that you can implement both approaches simultaneously. The former is useful when you want to implement different sorting strategies (e.g. by name, by date, by size etc.). The latter is useful if you want to make use of the concept of native ordering and the standard sort functions within the Java lib.
Check out the Java tutorial on Object Ordering
If you implement Comparable and use your own compareTo method that does what you need.
Another option is to use a custom Comparator as indicated in many other answers.
A nice article showing both approaches can be found here.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am studying collections in Java, however, some collections are quite confusing.
According to my understanding, I have prepared the Override chart.Need your help to correct it and understand it properly.
Please correct if wrong.
One more question about TreeMap.
I read about TreeMap, it sorts elements by KEYS using natural or custom order specified by Comparator. However, in some tutorials, it is specified that it can be sorted by values instead of keys. Is it correct or should we sort by keys only?
Update :
Sorry if my question feels bit ambiguous.
I am assuming I am putting my custom object of type Customer(java class) in each collection.
In key value pair collections, I am using Customer as key.
Which methods are compulsory to override for a collection with custom
Objects as key, value or element ?
There is no compulsion to override the methods of the collection classes. Collection API provides many classes like List (preserves the order of elements), Set (eliminates duplicates), Map (stores elements as key value pairs), etc.. which you can choose and use them directly depending upon your actual use case.
For TreeMap, Is it correct or should we sort by keys only ?
TreepMap sorts the elements by ordering the keys. If you are looking for ordering the elements by value, you can do that in many ways for which you can look here.
Again, there is no compulsion that you need do the ordering of the Map by key or value, it depends upon your project/business requirement.
UPDATE:
If I want to use hashmap of Customer class, as specified in book its
required to override hashcode and equals methods to work properly.
Yes, for custom classes like Customer, you need to override equals() and hashcode() so that the collection classes know how two Customer objects are equal. For example, when you are working with Set, to eliminate duplicates, Set needs to find how two Customer objects are equal so that it can preserve only one object.
Also, on the other side, if you want to order the elements (to be stored inside a collection), you need to override compare from Comparator or compareTo() from Comparable.
To summarise, refer the below basics:
override equals() and hashcode() whenever there is a need to find the object equality
override compare() or compareTo() for ordering requirements
This question already has answers here:
When to use Comparable and Comparator
(19 answers)
Closed 6 years ago.
why there is two interface comparable and comparator in java for sorting the collections?
both are doing the same task it seems... confusion on this sorting technique? Please advise
One might want to sort given objects in other way then the it was defined in the given object (using Comparable), that's why there is Comparator available.
Comparable - used in given class to define the default/natural ordering sorting
Comparator - used by foreign code (e.g. from different library) to sort the data in different way, or to add sorting to class that doesn't define Comparable, or to add different sorting order (e.g. sometimes you might want to sort strings case insensitive and sometimes case sensitive).
This question already has answers here:
When should a class be Comparable and/or Comparator?
(11 answers)
Closed 7 years ago.
Employee ID sort can be done using Comparable also as well as Comparator also but Why we go for Comparable when it comes to ID Sorting and why we go for Comparator when it comes to Name's sorting etc...?? Why can't we use Only Comparator for all the work???
If you want, you can use Comparator only. It allows you to freely define arbitrary ways to order object instances (independent of the object's own implementation).
The idea behind Comparable is that there may be a "natural" way to compare instances of some classes. For example, String can be compared to other Strings (to get lexicographical ordering). The class can then "advertise" this natural ordering and make it conveniently accessible.
I don't know if it makes sense for your Employee class to declare ID ordering "natural". Either way, you can only "promote" one order to be the natural one (and it cannot be changed without changing the implementation and contract of the class, so choose wisely).
Comparable is usually used to define a natural ordering (or you can call it a default ordering) on the instances of the class in which it is implemented.
In your Employee example (which is not detailed enough), I can assume that the employee ID is a unique identifier that identifies each employee, so it makes a good candidate for use in the definition of the natural ordering.
The Comparator interface allows us to implement additional orderings on instances of the Employee class, such as ordering by name, age, etc...
You could use just Comparator, but whenever a class has a natural ordering, it makes sense to implement Comparable, which allows you to use some classes and methods that require ordering (TreeSet, Collections.sort(), etc...) without having to pass a Comparator instance.
This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
difference between compare() and compareTo()
Java: What is the difference between implementing Comparable and Comparator?
What are the keys differences between Comparable and Comparator.
and which is preferred over the other in what scenarios?
Thanks
Updated - GOOD LINK WITH EXAMPLE!!
http://www.digizol.com/2008/07/java-sorting-comparator-vs-comparable.html
When your class implements Comparable, the compareTo method of the class is defining the "natural" ordering of that object. That method is contractually obligated (though not demanded) to be in line with other methods on that object, such as a 0 should always be returned for objects when the .equals() comparisons return true.
A Comparator is its own definition of how to compare two objects, and can be used to compare objects in a way that might not align with the natural ordering.
For example, Strings are generally compared alphabetically. Thus the "a".compareTo("b") would use alphabetical comparisons. If you wanted to compare Strings on length, you would need to write a custom comparator.
In short, there isn't much difference. They are both ends to similar means. In general implement comparable for natural order, (natural order definition is obviously open to interpretation), and write a comparator for other sorting or comparison needs.
Comparator provides a way for you to provide custom comparison logic for types that you have no control over.
Comparable allows you to specify how objects that you are implementing get compared.
Obviously, if you don't have control over a class (or you want to provide multiple ways to compare objects that you do have control over) then use Comparator.
Otherwise you can use Comparable.
I have a list of objects and I want to sort by passing the objects' field names and an order (ascending or descending). For example, my object is:
class Person{
private String name;
private String age;
//getters and setters
..........
}
I will pass List personList, String name, and boolean isAscending to an API method for sorting the personList. I can implement this by writing an implementation class for Comparator but I want to have a generic method.
That is, if I have Address object, I should be able to sort Address object list by its field name (for ex: streetName).
Basically, I am looking for a generic sort method to sort any kind of list. Any such APIs available?
I'm assuming you actually have getters and setters for the properties you want to use. Using the private fields directly is probably a bad idea anyways.
You can use BeanComparator from commons-beanutils. To sort ascending, use new BeanComparator("name"), for descending new BeanCompartor("name", Collections.reverseOrder())
#Wouter Coekaerts's answer is the simplest way to do this.
However!
The problem with any solution that uses reflection under the hood is that reflective operations are significantly more expensive than their non-reflective (compiled code) equivalents. Typically 1 to 2 orders of magnitude more expensive.
In your case, the comparator is going to be called O(NlogN) times each time you sort the object list. If your application is going to be sorting large lists ... or small lists lots of times ... the overheads of using a reflective comparator could make a big difference to your application's overall performance.
If performance turns out to be an issue (and profiling tells you that the reflective comparator is at fault), the alternatives are:
Write the comparators by hand. This is the simplest and most performant solution, whether or not you think it is elegant.
Use run-time source code generation to generate comparator classes and then compile and load them.
Use run-time bytecode generation to generate comparator classes and load them.
These could be combined with a lookup / caching mechanism that stores the comparators in a hash table using a key that combines the class and the field name. (A cache is essential if you use the code generation approach. But you still need to consider whether any given generated comparator will be used often enough to justify the large once-off overhead of generating/compiling/loading a class.)
There is a functional barrier to passing a "string" to identify a field. But if there was a generic way api available it would probably ask you to use a map or to have a get("fieldname") method to get the field it sorts on.
I would use a Comparator instead of Comparable if you are going to change the way you sort.
Seems like you need a reflection API.
import java.lang.reflect.Field;
String fieldValue(Object obj, String fieldName) {
Class c = obj.class;
Field f = c.getField(fieldName);
return (String)f.get(obj);
}
There may be some leak of typing, but you can always fix it manually by checking field's type with f.getType().