I'm a C# developer trying to work on Java. I'm stuck in creating a dynamic comparator. below is the code
public class SortImpl implements Sort {
public SortImpl() {
}
public ArrayList<Comparable> sort(ArrayList<Comparable> var1) {
Comparator var2 = new Comparator() {
};
var1.sort(var2);
return var1;
}
}
But Comparator needs a type while creating a Comparator object. My ArrayList can be of any type like int, double, float. Please let me know what I am doing wrong.
As I can understand from your code snippet you trying to create sort implementation, not comparator itself.
A Comparator<T> is an object that compare two objects.
From JavaDoc:
int compare(T o1, T o2)
Compares its two arguments for order.
Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
Because list elements already Comparable they can be directly compared as o1.compareTo(o2).
Also sort should be defined as public <T extends Comparable> List<T> sort(List<T> var1).
You don't need to implement a Comparator at all if you use java.util.Collections for sorting the list: it will then be sorted according to the natural ordering of its elements:
public ArrayList<Comparable> sort(ArrayList<Comparable> var1) {
Collections.sort(var1);
return var1;
}
In Java you dont have to implement Comparators for those types (Integer, Float, Char, String, etc...) When you define a List, you will say what type it is:
List<Person> list = new ArrayList<Person>();
When you sort the list, you may use the Collections.sort(List list, Comparator comparator) method. You may invoke it like:
Collections.sort(list, new Comparator<Person>() {
public int compare(Personobject1, Personobject2) {
return 0;//Put your code here
}
});
Parameters:
o1 - the first object to be compared.
o2 - the second object to be compared.
Returns:
a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
See https://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html for more information
Related
I have added some Integers to an ArrayList of object type, and want it to be sorted. My code looks like:
List<Object> list = new ArrayList<Object>();
list.add(24);
list.add(2);
list.add(4);
Collections.sort(list); // getting error here
System.out.println("Sorted list ");
for (Object e : list) {
System.out.println(e);
}
I got the following compile-time error:
error : should implement java.lang.Compareble <? super java.lang.Object>
How should I resolve this issue?
Object class doesn't implement Comparable interface. If you're sure you're adding Integer you can use code as below and then perform sorting.
List<Integer> list = new ArrayList<Integer>();
From sort() method docs
Sorts the specified list into ascending order, according to the natural ordering of its elements. All elements in the list must implement the Comparable interface. Furthermore, all elements in the list must be mutually comparable (that is, e1.compareTo(e2) must not throw a ClassCastException for any elements e1 and e2 in the list).
The error message that your IDE generating is
The inferred type Object is not a valid substitute for the bounded parameter >
Which means that the Objects being put in that List must implement Comparable interface to accept in sort() method.
Object class not implementing comparable interface, hence the error which you are seeing.
Using Object of type in Generic is not advisable and use specific type. Since you are adding all integers to the list just change your declaration to
List<Object> intList = new ArrayList<Object>();
If any other object of your own type, just implement comparable interface in that class or pass a custom comparator as a second parameter to sort.
Since you have declared your list to have the type List<Object>, you are able to store anything into it, be it comparable or not.
The generic method Collections.sort(List) has a type signature which requires that your list has an element type which implement the Comparable interface, which ensures that all elements can be compared to each other, and it tells the sort method how to compare these elements, as said interface contains the method which can be called to compared two elements. In other words, it does not accept a List that could contain anything.
So is your case, you should change the declaration to
List<Integer> list = new ArrayList<>();
as you are only adding Integer objects. Integer is a type which implements Comparable as integer values have a natural order.
Note that you can simplify your code:
List<Integer> list = Arrays.asList(24, 2, 4);
Collections.sort(list);
System.out.println("Sorted list "+list);
The list returned by Arrays.asList does not support changing its size, but reordering the elements is supported, hence you can sort that list.
As a side note, in the rare case, you have a List<Object> whose type you can’t change, but you know for sure that it contains only elements being naturally comparable to each other, you can circumvent the type constraint of Collection.sort:
Collections.sort(list, null);
The method Collections.sort(List, Comparator) supports arbitrary element types as the second parameter tells how to compare them. As a special case, a comparator of null mandates natural order, but null passes every type check. But, of course, using this trick will backfire when the assumption about the elements is wrong.
Generally, you should ensure that the element type as declared at compile-type is appropriate for the desired operation. Here, using List<Integer> when the list is supposed to contain Integers is the right way.
Instead of doing Collections.sort(list), you can loop through the array and sort the objects from least to greatest.
you can do it like this:
for(int i = 0; i < intList.size(); i++) {
// if an integer is larger than any of the ones after it in the array, switch them.
}
the Object class does not implement the Comperable interface, hence it gives you this error. You should rather define it as List<Integer>, or define a custom comperator class and pass it as an aditional Argument.
public class Comp<T> implements Comparator<T>{
#Override
public int compare(T o1, T o2) {
if(o1 instanceof Integer && o2 instanceof Integer) {
int a = (Integer) o1;
int b = (Integer) o2;
return a-b;
}
return 0;
}
}
// Call it as
Collections.sort(list, new Comp<Object>());
But you may run in several Problems while using a List of Objects and a custom Comperator, since you could add everyting to this list.
I have a ArrayList having String, int, long, date type objects etc.
I want to sort these objects.
Can some one help me to do this?
if you have a ArrayList<Object> that contains different types of objects, e.g. String, Integer, Long, etc.
You can sort this ArrayList with a specific Comparator that will first use their class names and then use a method of comparison for each family of objects. All the classes must implement the Comparable interface - this is the case for String, Integer, Long, Date, Float, Double.
public List<Object> sortMultiClassList(List<Object> yourList) {
return Collections.sort(yourList, new Comparator<Object>() {
public int compare(Object o1, Object o2) {
if (o1.getClass() == o2.getClass()) {
if (o1 instanceof Comparable) {
return((Comparable)o1).compareTo((Comparable)o2);
}
else {
throw new IllegalArgumentException("Don't know how to compare");
}
}
else {
return o1.getClass().getName()
.compareTo(o2.getClass().getName());
}
}
});
}
Note : A java.util.Collection cannot contains primitive types like int, long, float, double, char.
You can sort an ArrayList with
list.sort();
regardless of the type.
if you have a custom class and you need a specific sorting order you can do
class MyClass implements Comparator<MyClass> {
public int compareTo(MyClass other) {
// write your comparison here
}
}
Or you can create a comparator on the fly with Comparator.
list.sort(Comparator.comparing(t -> t.first)
.thenComparing(t -> t.numbers).reversed()
.thenComparing(t -> t.date)
.thenComparing(t -> t.string));
You can sort List collections using the java.util.Collections.sort() method.
You can sort these two types of List's.
ArrayList
LinkedList
Read more about sorting using comparator
This question already has answers here:
Sorting an ArrayList of objects using a custom sorting order
(12 answers)
Closed 8 years ago.
I want to sort this list of Emp objects in ascending order based on the marks field.
List<Emp> emp= new ArrayList<Emp>();
public class Emp implements Serializable {
private String empname;
private String section;
private int empId;
private int marks;
...
You need to write a comparator, otherwise the Sort method assumes which fields you want use when sorting.
Collections.sort(emp, new Comparator<Emp>() { public int compare(Emp one, Emp two) {
return one.marks.compareTo(two.marks);
});
In my example i treated the field marks as public, replace one.marks with a getter if you so choose.
Also since you're using ints which do not have a compareTo, do like so:
Collections.sort(list, new Comparator<Emp>() {
public int compare(Emp one, Emp two) {
int cmp = one.getMarks() > two.getMarks() ? +1 : one.getMarks() < two.getMarks() ? -1 : 0;
return cmp;
}
});
You can use a comparator object to sort.
Collections.sort();
does the sorting.
This will work with your List. The method to be used is compareTo.
if (list.size() > 0) {
Collections.sort(list, new Comparator<Emp>() {
#Override
public int compare(final Emp object1, final Emp object2) {
return object1.getMarks().compareTo(object2.getMarks());
}
} );
}
There are two main ways of supporting object comparisons in Java.
You can have your class implement the Comparable interface, which is acceptable when your objects have a natural ordering that you're relying on (for example, alphabetical ordering for strings). This requires classes to implement a compareTo method which defines the comparison rule between instances.
The standard alternative is to instantiate a Comparator for your class, and specify the comparison rule in a compare method.
In your case, the latter option seems more appropriate. The mechanics of the compare method are fairly simple: it takes two instances of your class, returns a negative value if the first is "less than" the second, a positive number if it is "greater", and 0 if they are "equal". For integer-based comparisons, like comparing by marks, the quick trick is to return the difference of the numbers.
Once you have your Comparator defined, sorting is as simple as invoking the Collections.sort method, opting for the method signature which takes a List and a specified Comparator.
List<Emp> emps = new ArrayList<Emp>();
// populate list...
Comparator<Emp> empComparator = new Comparator<Emp>() {
public int compare(Emp e1, Emp e2) {
return e2.getMarks() - e2.getMarks();
}
};
Collections.sort(emps, empComparator);
How can I sort an array in Java/Android alphabetically?
After that I want to provide the ordered array to a ListView.
Arrays.sort() should do the trick
http://docs.oracle.com/javase/6/docs/api/java/util/Arrays.html
it can be done just using
Arrays.sort(myarray);
For more complex sorting see Comparator
Example:
Arrays.sort(some_array, new Comparator<SomeObject>() {
#Override
public int compare(SomeObject entry1, SomeObject entry2) {
return entry1.getSomeData().compareTo(entry2.getSomeData());
}
});
Objects that implement the Comparable interface (like Strings) have a natural ordering (as defined by its compareTo method) so you can just use Arrays.sort():
Arrays.sort(yourArrayOfComparables);
It will directly sort the array and will not make a copy.
If you want a more specific sort that isn't considered "natural" you can create a Comparator for that object:
Comparator<MyObject> comp = new Comparator<MyObject>() {
public int compare(MyObject obj1, MyObject obj2) {
//Code here
}
}
Arrays.sort(yourArrayOfObjects, comp);
The rules for Comparators and Comparables (where the first object is the object itself) is: return a negative if the first object is less than the second, positive for the other way round and 0 if they're equal.
I have an unsorted linked list. To sort it, I thought I'd put the values into a TreeSet with a comparator supplied, then return those values as a new linked list. Yet, it fails.
Comparator:
public class SortSpeciesByCommonName implements Comparator<Species> {
/**
* a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.
*/
#Override
public int compare(Species arg0, Species arg1) {
return arg0.getName().compareTo(arg1.getName()); //arg.getName() is String
}
}
Sorting function:
public static LinkedList<Species> sortedAnimals(LinkedList<Species> animals) {
TreeSet<Species> sortedBreeds = new TreeSet<Species>(new SortSpeciesByCommonName());
sortedBreeds.addAll(animals);
return new LinkedList<Species>(sortedBreeds);
}
When testing the values, everything appears to still be in insertion order.
Why don't you use Collections.sort(List,Comparator):
LinkedList<Species> sorted = new LinkedList<Species>(arg);
Collections.sort(sorted, new Comparator<Species>() {
#Override
public int compare(Species s1, Species s2) {
return s1.getName().compareTo(s2.getName());
}
});
We cannot really debug your program and why the list isn't sorted. Can you provide a test case? What's the signature of Species.getName()? Is it a String?
This doesn't answer your question directly, but you may find it easier to just use Collections.sort, passing in your list and comparator. Saves using a TreeSet.