Showing posts with label Comparator. Show all posts

Example of Comparator in Java

Comparator<T>
A comparison function, which imposes a total ordering on some collection of objects. Comparators can be passed to a sort method (such as Collections.sort or Arrays.sort) to allow precise control over the sort order. Comparators can also be used to control the order of certain data structures (such as sorted sets or sorted maps), or to provide an ordering for collections of objects that don't have a natural ordering.

You can use Comparable when you want natural ordering on class. And you would also like to read How to sort List of Bean in Java? using Comparator and Comparable and How to sort Array in Ascending, Descending and Mixed mode in Java?

Source code (Item.java)
import java.util.Comparator;

public class Item {

    private String name;
    private Double price;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }
    
    /**
     * Comparator to sort {@link Item} in ascending order by name.
     */
    public Comparator<Item> orderByNameASC(){
        return new Comparator<Item>() {
            @Override
            public int compare(Item o1, Item o2) {
                if(o1 != null && o1.getName() != null
                        && o2 != null && o2.getName() != null){
                    return o1.getName().compareTo(o2.getName());
                }
                return -1;
            }
        };
    }
    
    /**
     * Comparator to sort {@link Item} in descending order by name.
     */
    public Comparator<Item> orderByNameDESC(){
        return new Comparator<Item>() {
            @Override
            public int compare(Item o1, Item o2) {
                if(o1 != null && o1.getName() != null
                        && o2 != null && o2.getName() != null){
                    return o2.getName().compareTo(o1.getName());
                }
                return -1;
            }
        };
    }

    @Override
    public String toString() {
        return "Item{" + "name=" + name + ", price=" + price + '}';
    }
}

Source code (ComparatorExample.java)
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * Example of Comparator.
 * @author javaQuery
 * @date 9th August, 2016
 * @Github: https://github.com/javaquery/Examples 
 */
public class ComparatorExample {

    public static void main(String[] args) {
        Item samsung = new Item();
        samsung.setName("samsung");

        Item iPhone = new Item();
        iPhone.setName("iphone");

        List<Item> items = new ArrayList<Item>(2);
        items.add(samsung);
        items.add(iPhone);

        List<Item> clonedItems = new ArrayList<Item>(items);
        new ComparatorExample().usingPredefinedComparator(clonedItems);
        new ComparatorExample().usingInLineExpression(clonedItems);
        new ComparatorExample().usingLambdaExpression(new ArrayList<Item>(items));
    }

    /**
     * Print list to console
     *
     * @param items
     */
    private void printListData(List<Item> items) {
        for (Item item : items) {
            System.out.println(item);
        }
    }

    /**
     * Considering you've already created Comparators in your model.
     *
     * @param items
     */
    private void usingPredefinedComparator(List<Item> items) {
        System.out.println("Using Predefined Comparator (NAME#ASC)");
        System.out.println("===============================================");
        System.out.println("Before sort:");
        printListData(items);
        System.out.println("After sort(orderByNameASC):");
        Collections.sort(items, new Item().orderByNameASC());
        printListData(items);
    }
    
    /**
     * This is same as PredefinedComparator. 
     * Its only to show you how to use {@link Comparator} in-line.
     * @param items 
     */
    private void usingInLineExpression(List<Item> items){
        System.out.println("===============================================");
        System.out.println("Using Inline Expression (NAME#DESC)");
        System.out.println("===============================================");
        System.out.println("Before sort:");
        printListData(items);
        System.out.println("After sort(orderByNameDESC):");
        Collections.sort(items, new Comparator<Item>(){

            @Override
            public int compare(Item o1, Item o2) {
                if(o1 != null && o1.getName() != null
                        && o2 != null && o2.getName() != null){
                    return o2.getName().compareTo(o1.getName());
                }
                return -1;
            }
             
        });
        printListData(items);
    }
    
    /**
     * Using Lambda Expression in Java 1.8 or above.
     * @param items 
     */
    private void usingLambdaExpression(List<Item> items){
        System.out.println("===============================================");
        System.out.println("Using Lambda Expression (NAME#DESC)");
        System.out.println("===============================================");
        System.out.println("Before sort:");
        printListData(items);
        System.out.println("After sort(orderByNameASC):");
        Collections.sort(items, (Item o1, Item o2) -> {
            if(o1 != null && o1.getName() != null
                    && o2 != null && o2.getName() != null){
                return o1.getName().compareTo(o2.getName());
            }
            return -1;
        });
        printListData(items);
    }
}

Output
Using Predefined Comparator (NAME#ASC)
===============================================
Before sort:
Item{name=samsung, price=null}
Item{name=iphone, price=null}
After sort(orderByNameASC):
Item{name=iphone, price=null}
Item{name=samsung, price=null}
===============================================
Using Inline Expression (NAME#DESC)
===============================================
Before sort:
Item{name=iphone, price=null}
Item{name=samsung, price=null}
After sort(orderByNameDESC):
Item{name=samsung, price=null}
Item{name=iphone, price=null}
===============================================
Using Lambda Expression (NAME#ASC)
===============================================
Before sort:
Item{name=samsung, price=null}
Item{name=iphone, price=null}
After sort(orderByNameASC):
Item{name=iphone, price=null}
Item{name=samsung, price=null}

How to sort Array in Ascending, Descending and Mixed mode in Java?

java.util.Arrays
java.util.Arrays class provides many options for sorting an Array. We will sort Array in Ascending, Descending and Mixed mode(1st/first to kth in Ascending order and k+1th to nth/last in Descending order, you can choose different position for 1st,kth and nth).

In addition this question was asked in leading Multi National Company(MNC). Its worth understanding code for future interview of yours.

Source Code
public class SortArray {

    public static void main(String[] args) {
        Integer[] intSortArrayAscending = {25, 9, 23, 1, 4, 90, 99};
        Integer[] intSortArrayDescending = {25, 9, 23, 1, 4, 90, 99};
        Integer[] intSortArrayMixedMode = {25, 9, 23, 1, 4, 90, 99};

        /* Sort Array in Ascending order */
        Arrays.sort(intSortArrayAscending);
        
        /* Print array */
        System.out.print("Ascending order: ");
        for (int i : intSortArrayAscending) {
            System.out.print(i + ",");
        }

        System.out.println("\n------------------------");

        /* Sort Array in Descending order */
        SortArray objSortArray = new SortArray();
        /* Use Comparator to sort Array in Descending order */
        Arrays.sort(intSortArrayDescending, objSortArray.comparatorDescending());

        /* Print array */
        System.out.print("Descending order: ");
        for (int i : intSortArrayDescending) {
            System.out.print(i + ",");
        }
        System.out.println("\n------------------------");

        System.out.println("Mixed mode sorting:");
        /**
         * Mixed mode Sorting
         * Sort 1st/first position to kth in Ascending order
         * and
         * Sort k+1th position to nth/last in Descending order
         */
        
        /* I used middle point as pivotPoint */
        int pivotPosition = intSortArrayMixedMode.length / 2;
        System.out.println("Ascending order from element 1 to " + pivotPosition);
        System.out.println("Descending order from element " + (pivotPosition + 1) + " to " + intSortArrayMixedMode.length);

        /* Arrays.sort(int[] a, int fromIndex, int toIndex) */
        Arrays.sort(intSortArrayMixedMode, 0, pivotPosition);

        /*  sort(T[] a, int fromIndex, int toIndex, Comparator<? super T> c) */
        Arrays.sort(intSortArrayMixedMode, pivotPosition, intSortArrayMixedMode.length, objSortArray.comparatorDescending());

        /* Print array */
        for (int i : intSortArrayMixedMode) {
            System.out.print(i + ",");
        }
    }

    /**
     * Comparator for Descending order
     */
    public Comparator<Integer> comparatorDescending() {
        return new Comparator<Integer>() {

            @Override
            public int compare(Integer o1, Integer o2) {
                if (o1 < o2) {
                    return 1;
                } else {
                    return -1;
                }
            }
        };
    }
}

Output
Ascending order: 1,4,9,23,25,90,99,
------------------------
Descending order: 99,90,25,23,9,4,1,
------------------------
Mixed mode sorting:
Ascending order from element 1 to 3
Descending order from element 4 to 7
9,23,25,99,90,4,1,


How to sort List of Bean in Java?

Collection Framework Sort


In my previous article How to sort a List in Java? We have seen how we can sort List<String>. This time we'll understand code of How we can sort List<Bean>.

Storing data in bean is common practice in current industry. Bean structure allows us to get specific property of object. Hope you all are aware of what is bean so lets not waste time and understand the code.

Background
We have User object that holds two property Firstname and Lastname. We will sort the List on Firstname in ascending order. There are two technique you can use to sort an object and we'll checkout one by one.

Technique One
Say you have access to your bean class and can modify the class file then by implementing Comparable interface you can perform sorting.
/**
 * @author javaQuery
 */
public class User implements Comparable<User> {

    private String Firstname;
    private String Lastname;

    public String getFirstname() {
        return Firstname;
    }

    public void setFirstname(String Firstname) {
        this.Firstname = Firstname;
    }

    public String getLastname() {
        return Lastname;
    }

    public void setLastname(String Lastname) {
        this.Lastname = Lastname;
    }

    /**
     * This `compareTo` used to compare two `User` object,
     * Which internally uses `compareTo` of String class to compare two String values.
     * @param obj
     * @return 
     */
    @Override
    public int compareTo(User obj) {
        /* Check object and Firstname are not null */
        if(obj != null && obj.Firstname != null){
            /* We will use `compareTo` of String class */
            /* For ascending order */
            return this.Firstname.compareTo(obj.Firstname);
   
            /* For descending order */
            /* return obj.Firstname.compareTo(this.Firstname) */
        }else{
            return -1;
        }
    }
 
 /* If you want to sort on `int` value then uncomment following code */
//   @Override
//    public int compareTo(User obj) {
//        /* Check object and id is not null and 0 */
//        if (obj != null && obj.getId() != 0) {
//            /* For ascending order */
//            return this.getId() - obj.getId();
//
//            /* For descending order */
//            /* return obj.getId() - this.getId(); */
//        } else {
//            return -1;
//        }
//    }
}
Source Code
import com.javaquery.beans.User;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * @author javaQuery
 */
public class SortingObjectListExample {

    public static void main(String[] args) {
        /* Create object of User */
        User user1 = new User();
        /* Set Firstname of User */
        user1.setFirstname("Vicky");
        /* Set Lastname of User */
        user1.setLastname("Thakor");

        User user2 = new User();
        user2.setFirstname("Chirag");
        user2.setLastname("Thakor");

        User user3 = new User();
        user3.setFirstname("Heer");
        user3.setLastname("Thakor");

        User user4 = new User();
        user4.setFirstname("Yogita");
        user4.setLastname("Thakor");

        User user5 = new User();
        user5.setFirstname("Riddhi");
        user5.setLastname("Thakor");

        User user6 = new User();
        user6.setFirstname("Xender");
        user6.setLastname("Thakor");

        /* Add Users in List<User> */
        List<User> listUser = new ArrayList<User>();
        listUser.add(user4);
        listUser.add(user6);
        listUser.add(user1);
        listUser.add(user5);
        listUser.add(user2);
        listUser.add(user3);

        System.out.println("Initial List");
        System.out.println("------------------------");
        for (User user : listUser) {
            System.out.println(user.getFirstname() + " " + user.getLastname());
        }
        System.out.println("------------------------");

        Collections.sort(listUser);
        System.out.println("List after Collections.sort(List<T> list)");
        System.out.println("------------------------");
        for (User user : listUser) {
            System.out.println(user.getFirstname() + " " + user.getLastname());
        }
    }
}
Output of the above code is given at the end of the article as both technique gives same output.

Technique Two
Say if you don't have access to your bean(bind in jar) and still you want to sort on specific property then by creating custom Comparator you can achieve same.
/**
 * @author javaQuery
 */
public class User{

    private String Firstname;
    private String Lastname;

    public String getFirstname() {
        return Firstname;
    }

    public void setFirstname(String Firstname) {
        this.Firstname = Firstname;
    }

    public String getLastname() {
        return Lastname;
    }

    public void setLastname(String Lastname) {
        this.Lastname = Lastname;
    }
}
Source code
import com.javaquery.beans.User;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * @author javaQuery
 */
public class SortingObjectListExample {

    public static void main(String[] args) {
        /* Create object of User */
        User user1 = new User();
        /* Set Firstname of User */
        user1.setFirstname("Vicky");
        /* Set Lastname of User */
        user1.setLastname("Thakor");

        User user2 = new User();
        user2.setFirstname("Chirag");
        user2.setLastname("Thakor");

        User user3 = new User();
        user3.setFirstname("Heer");
        user3.setLastname("Thakor");

        User user4 = new User();
        user4.setFirstname("Yogita");
        user4.setLastname("Thakor");

        User user5 = new User();
        user5.setFirstname("Riddhi");
        user5.setLastname("Thakor");

        User user6 = new User();
        user6.setFirstname("Xender");
        user6.setLastname("Thakor");

        /* Add Users in List<User> */
        List<User> listUser = new ArrayList<User>();
        listUser.add(user4);
        listUser.add(user6);
        listUser.add(user1);
        listUser.add(user5);
        listUser.add(user2);
        listUser.add(user3);

        System.out.println("Initial List");
        System.out.println("------------------------");
        for (User user : listUser) {
            System.out.println(user.getFirstname() + " " + user.getLastname());
        }
        System.out.println("------------------------");

        /* Create object of `SortingObjectListExample` */
        SortingObjectListExample objSortingObjectListExample = new SortingObjectListExample();
        /* Get custom Comparator */
        Comparator<User> objComparator = objSortingObjectListExample.getComparator();

        /* Sort List<User> using custom Comparator */
        Collections.sort(listUser, objComparator);
        System.out.println("List after Collections.sort(List<T> list)");
        System.out.println("------------------------");
        for (User user : listUser) {
            System.out.println(user.getFirstname() + " " + user.getLastname());
        }
    }

    /* Create custom Comparator */
    public Comparator<User> getComparator() {
        return new Comparator<User>() {

            @Override
            public int compare(User obj1, User obj2) {
                /* Check obj1 and obj2 are not null and also check Firstname of both objects are not null */
                if (obj1 != null && obj2 != null
                        && obj1.getFirstname() != null && obj2.getFirstname() != null) {
                    /* Use `compareTo` of String class to compare two String values */
                    /* For ascending order */
                    return obj1.getFirstname().compareTo(obj2.getFirstname());
   
                    /* For descending order */
                    /* return obj2.getFirstname().compareTo(obj1.getFirstname()) */
                } else {
                    return -1;
                }
            }
        };
    }
}
Output
Initial List
------------------------
Yogita Thakor
Xender Thakor
Vicky Thakor
Riddhi Thakor
Chirag Thakor
Heer Thakor
------------------------
List after Collections.sort(List<T> list)
------------------------
Chirag Thakor
Heer Thakor
Riddhi Thakor
Vicky Thakor
Xender Thakor
Yogita Thakor