How to Use Comparator in Java to Sort

Sorting using Comparator- Descending order (User defined classes)

You can do the descending sort of a user-defined class this way overriding the compare() method,

Collections.sort(unsortedList,new Comparator<Person>() {
@Override
public int compare(Person a, Person b) {
return b.getName().compareTo(a.getName());
}
});

Or by using Collection.reverse() to sort descending as user Prince mentioned in his comment.

And you can do the ascending sort like this,

Collections.sort(unsortedList,new Comparator<Person>() {
@Override
public int compare(Person a, Person b) {
return a.getName().compareTo(b.getName());
}
});

Replace the above code with a Lambda expression(Java 8 onwards) we get concise:

Collections.sort(personList, (Person a, Person b) -> b.getName().compareTo(a.getName()));

As of Java 8, List has sort() method which takes Comparator as parameter(more concise) :

personList.sort((a,b)->b.getName().compareTo(a.getName()));

Here a and b are inferred as Person type by lambda expression.

Creating a comparator to pass to .sort() in java not suitable method error

Collections.sort accepts a Comparator<T> as the second argument, you are giving it a Comparable<T>. This is why the error pops up.

Even if Collections.sort did accept a Comparable<T>, your implementation violates the general contract of Comparable.

You seem to just want to sort the strings in reverse order. You can just do something like this:

Collections.sort(directories, Comparator.reverseOrder());

If I misunderstood you and you actually want to sort it in some custom way, you can do something like this:

Collections.sort(directories, Comparator.comparing(s -> /*map the string to something you want to compare*/));

Java: Sort a list of Objects using Comparator with second word of the property

In Java 8 Streams mode:

Comparator<? super Animal> animalComparator = (a, b) -> {
StringTokenizer firstTokenizer = new StringTokenizer(a.getName(), " ");
firstTokenizer.nextToken();
StringTokenizer secondTokenizer = new StringTokenizer(b.getName(), " ");
secondTokenizer.nextToken();
return firstTokenizer.nextToken().compareTo(secondTokenizer.nextToken());
};

myList = myList.stream().sorted(animalComparator).collect(Collectors.toList());

How to perform sorting based on Comparator keeping original sort intact in Java

This is not because your Employee class already has a default ordering, that using Collections.sort with a custom comparator will introduce a new layer of ordering.

For example let's say that the default ordering of your Employees is by their salary in ascending order. Now let's say you want to sort them by salary in descending order.

According to your logic how this will behave?

Collections.sort(employees, new SalaryDescendingComparator());

The fact is that when you provide a custom comparator to Collections.sort, it will use only this one and not the sorting mechanism that you implemented in your Employee class.

As the doc states:

Sorts the specified list according to the order induced by the
specified comparator.

So because the SalaryComparator compares employees only by their salary, that's why you get this output.

If you want to sort by name first and then by salary, you'll have to do this in one time, i.e :

public class Employee implements Comparable<Employee> {

private int empSalary;
private String empName;

@Override
public int compareTo(Employee e) {
int cmp = this.empName.compareTo(e.empName);
return cmp != 0 ? cmp : Integer.compare(empSalary, e.empSalary);
}

}

How to use Comparator with conditions in java

Assuming that sortlist is a list of SortCriteria, which is a class like this:

class SortCritera {
private String key;
private String order;

public String getKey() {
return key;
}

public String getOrder() {
return order;
}

// constructors, setters...
}

You first need a HashMap<String, Comparator<Employee>> to store all the corresponding comparators for each possible key:

HashMap<String, Comparator<Employee>> comparators = new HashMap<>();
comparators.put("name", Comparator.comparing(Employee::getName));
comparators.put("age", Comparator.comparing(Employee::getAge));
// ...

Then you can loop through the sortlist and keep calling thenComparing:

Comparator<Employee> comparator = comparators.get(sortlist.get(0).getKey());
if (sortlist.get(0).getOrder().equals("DESC")) {
comparator = comparator.reversed();
}
for(int i = 1 ; i < sortlist.size() ; i++) {
if (sortlist.get(i).getOrder().equals("DESC")) {
comparator = comparator.thenComparing(comparators.get(sortlist.get(i).getKey()).reversed());
} else {
comparator = comparator.thenComparing(comparators.get(sortlist.get(i).getKey()));
}
}
// now you can sort with "comparator".

As Holger has suggested, you can use the Stream API to do this as well:

sortlist.stream().map(sc -> {
Comparator<Employee> c = comparators.get(sc.getKey());
return sc.getOrder().equals("DESC")? c.reversed(): c;
}).reduce(Comparator::thenComparing)
.ifPresent(x -> Collections.sort(originalList, x));

How to use a separate comparator class to sort an array list

I would use

Collections.sort(list, RationalComparator.INSTANCE);

where the comparator looks like

enum RationalComparator implements Comparator<Rational> {
INSTANCE;

public int compare(Rational a, Rational b) {
// do your comparison here
}
}

Array Sorting Using A Comparator in Java

I just put together this simple example to show two different ways of using a Comparator:

import java.util.Arrays;
import java.util.Comparator;

public class ArraySort
{
public static void main(String[] args)
{
String[][] data = new String[][]
{
new String[] { "Casablanca", "Warner Brothers", "1942" },
new String[] { "Citizen Kane", "RKO Pictures", "1941" },
new String[] { "Singin' in the Rain", "MGM", "1952" },
new String[] { "The Wizard of OZ", "MGM", "1930"},
new String[] { "AaaaaThe Wizard of OZ", "MGM", "1943"}
};

Arrays.sort(data, new Comparator<String[]>() {

@Override
public int compare(final String[] entry1, final String[] entry2) {
final String field1 = entry1[0];
final String field2 = entry2[0];
return field1.compareTo(field2);
}
});

print(data);

System.out.println();

Arrays.sort(data, new SortByDate());

print(data);

System.out.println();

Arrays.sort(data, new SortByCompany());

print(data);
}

public static void print(String[][] data){
for (String[] array : data){
for (String s : array){
System.out.print(s + " ");
}
System.out.println();
}
}

}

public class SortByDate implements Comparator<String[]>{
@Override
public int compare(final String[] entry1, final String[] entry2) {
final String field1 = entry1[2];
final String field2 = entry2[2];
return field1.compareTo(field2);
}
}

public class SortByCompany implements Comparator<String[]>{
@Override
public int compare(final String[] entry1, final String[] entry2) {
final String field1 = entry1[1];
final String field2 = entry2[1];
return field1.compareTo(field2);
}
}

Output:

AaaaaThe Wizard of OZ MGM 1943 
Casablanca Warner Brothers 1942
Citizen Kane RKO Pictures 1941
Singin' in the Rain MGM 1952
The Wizard of OZ MGM 1930

The Wizard of OZ MGM 1930
Citizen Kane RKO Pictures 1941
Casablanca Warner Brothers 1942
AaaaaThe Wizard of OZ MGM 1943
Singin' in the Rain MGM 1952

The Wizard of OZ MGM 1930
AaaaaThe Wizard of OZ MGM 1943
Singin' in the Rain MGM 1952
Citizen Kane RKO Pictures 1941
Casablanca Warner Brothers 1942


Related Topics



Leave a reply



Submit