Comparable vs Comparator in Java
Tags: beginners, codenewbie, java, programming
Published: 2021-08-01 23:21:35

Hi guys, today I will write about a question that I was have been facing recently. I was writing a code and I needed to compare two things and I was in doubt about which comparator to use, then I was searching for comparators and find two the **Comparable** and the **Comparator**, reading about both I decided to write this post.

Now, I will contextualize a bit about Comparable. This is an interface that is implemented in the class that wants to create a comparison, this class that implements is obliged to implements a method called *compareTo()*, this method receives a value and compares it with something that is implemented inside the method.

To be able to explain this better I created the Product class, to be used, how to see below.

```Java
public class Product implements Comparable<Product>{
    private String name;
    private int quantity;
    private BigDecimal price;

    public Product(String name, int quantity, BigDecimal price) {
        this.name = name;
        this.quantity = quantity;
        this.price = price;
    }

  // Getters, Setters and toString

    @Override
    public int compareTo(Product product) {

        if (this.quantity > product.getQuantity()) return 1;

        return -1;
    }
}
```

In that class was implemented the interface Comparable that receives a type of comparing, in our case, it is **Product**, in the class, we have three variables, like name, quantity, and price. Was created methods like constructors, getters, setters, and toString, but methods like getters, setters, and toString not were showed because it's not important to explain.

How we implement the interface, we have that creates a method *compareTo()* doing Override. This method is designated to create the logic of comparison for the class, in our case, we receive a *Product* and we do a comparison of quantity, pay attention, the return of the method is an integer, if the return is the first case of comparison then return 1 but if not then return -1, the implementation of method *compareTo()* understands this and return the correct comparison.

Now, with the Product class created we can start the Main class, in this class, we have the create the objects of Product, was added to a list, and for the order, we use the method Sort of the class Collections, this method receives an interface comparable like, the Product class implements comparable, we inherited from her, then we can pass the list that was created to method *sort()* the list by quantity.

```Java
public static void main(String[] args) {
        Product product1 = new Product("Laptop Dell", 12, new BigDecimal(600));
        Product product2 = new Product("Laptop Lenovo", 13, new BigDecimal(650));
        Product product3 = new Product("Laptop Macbook", 6, new BigDecimal(1200));

        List<Product> products = Arrays.asList(product1, product2, product3);

        Collections.sort(products);

        products.forEach(System.out::println);
    }
```

With the Product class sorted by quantity.

```Java
Product{name='Laptop Macbook', quantity=6, price=1200}
Product{name='Laptop Dell', quantity=12, price=600}
Product{name='Laptop Lenovo', quantity=13, price=650}
```

Now we go speak about the Comparator class, this class is an interface functional having only an abstract method, this allows us to instantiate the comparator class without the need to implement this interface. This is only possible after Java 8, which added the functional interfaces. That's why we are going to rebuild the Product class.

```Java
public class Product {
    private String name;
    private int quantity;
    private BigDecimal price;

    public Product(String name, int quantity, BigDecimal price) {
        this.name = name;
        this.quantity = quantity;
        this.price = price;
    }

  // Getters, Setters and toString
}
```

With appropriate modifications made we can create an instance of the interface, this allows the creation of many ways to treat the data stream without the need to create methods or implements an interface. We are going to see some ways the create a comparable.

```Java
public static void main(String[] args) {
        Product product1 = new Product("Laptop Dell", 12, new BigDecimal(600));
        Product product2 = new Product("Laptop Lenovo", 13, new BigDecimal(650));
        Product product3 = new Product("Laptop Macbook", 6, new BigDecimal(1200));

        List<Product> products = Arrays.asList(product1, product2, product3);

        Comparator<Product> comparator = (p1, p2) -> {
            if (p1.getQuantity() > p2.getQuantity()) {
                return -1;
            } else {
                return 1;
            }
        };

        Collections.sort(products, comparator);

        products.forEach(System.out::println);
}
```

In the example above, we can see that was instanced the Comparator class and created the comparison, where was compared the quantity of two values and return the biggest. With the comparator created, we can execute the *Collection.sort(products, comparator)*, this comparison will go executed into the list in each value, so sorting the list per biggest quantity. Furthermore, we can create a method cleaner and use the method *.comparing()*, this is a static method the Comparator class has, this method implements code to comparation, and receive a unique value to be compared.

```Java
public static void main(String[] args) {

        List<Product> products = Arrays.asList(product1, product2, product3);

        products.sort(Comparator.comparing(p1 -> p1.getQuantity()));

        products.forEach(System.out::println);
    }
```

Now, we will see the last example, this example will modify the Product class, we will create specific methods to sort the elements of the class, was created the *quantityComparator*, we instanced of way static the Comparator class and create the code to comparation as in the previous example.

```Java
public class Product {
    private String name;
    private int quantity;
    private BigDecimal price;

    public Product(String name, int quantity, BigDecimal price) {
        this.name = name;
        this.quantity = quantity;
        this.price = price;
    }

  // Getters, Setters and toString

    public static Comparator<Product> quantityComparator = new Comparator<Product>() {
        @Override
        public int compare(Product p1, Product p2) {
            if (p1.getQuantity() > p2.getQuantity()) {
                return 1;
            }
            return -1;
        }
    };
}
```

In the Main class, we have the created the *Collections.sort(products, Product.quantityComparator)* and is called the method static quantityComparator, which presents way sort the list.

```Java
public static void main(String[] args) {

    List<Product> products = Arrays.asList(product1, product2, product3);

    Collections.sort(products, Product.quantityComparator);

    products.forEach(System.out::println);
}
```

Both ways are very used but have that pay attention to some things when using these interfaces.The Comparable interface creates a sort pattern to class, them when use methods to sort will use the way that was created as in the example, but we have a problem, will have only one type of comparation. The Comparator interface can be instanced and create ways comparison in various ways, can be the principal class or in other class that needs some comparing.

*Should be attention in some cases, Rules of business that are tied to that code and refactoring of code.*