Automation QA Testing Course Content

Java Comparators in-practice

 

You don’t know Comparators in-practice, Do You?


When I started learning about sorting objects in Java, I was bored with the interviewer’s favourite question—Comparable vs. Comparator.

So, I thought it was time to level up because merely knowing the difference between the above 2 interfaces will not make an efficient developer. As someone who has to write code, I need more substance to be able to put this to use every day.

So, I started to explore various coding problems that Comparators can solve. And that is what we will discuss today.

In Java, the Comparator interface defines custom ordering for objects. Using this interface, we can efficiently sort collections, arrays, and other data structures in a desired order.

When to Use the Comparator Interface:

The Comparator interface in Java provides a flexible way to define custom comparison logic for objects. It is used when:

  • The class of the objects being compared does not implement the Comparable interface.

HELPS to define different comparison criteria for sorting without modifying the original class or implementing the Comparable interface.

  • When you need different sorting criteria for different use cases or when you don’t have control over the class’s source code (e.g., if it’s part of a library). If you have control over the class and can modify its compareTo method to suit your needs, then go with Comparable.

Detailed GitHub documentation on Comparators — https://github.com/VarshaDas/Java-Code-Snippets/blob/main/ComparatorsDemo/README-Comparators.md

Relevant code links:

https://github.com/VarshaDas/Java-Code-Snippets/blob/main/ComparatorsDemo/ComparatorDemo.java


Coding Questions:

Let’s now see how we can incorporate Comparators and its APIs into our day-to-day coding problems.

But before that, a brief introduction to five important methods of the Comparator :

compare(T obj1, T obj2):

This method compares two objects for order.

It returns an int value:

  • Negative Integer: If obj1 is considered less than obj2.
  • Zero: If obj1 is considered equal to obj2.
  • Positive Integer: If obj1 is considered greater than obj2.

The compare method is the main method that needs to be implemented when creating a custom comparator. It defines the ordering of objects based on the logic specified in the implementation.

naturalOrder() and reverseOrder():

  • Comparator.naturalOrder(): Returns a comparator that imposes the natural ordering of the elements.

The “natural ordering” is the default ordering that is inherent to the data type. For primitive types and some classes, this corresponds to the standard numerical or lexicographic ordering.

For numeric types (IntegerDouble, etc.), it imposes ascending numerical order.

For characters (Character), it imposes the Unicode order.

For strings (String), it imposes lexicographic (dictionary) order.

  • Comparator.reverseOrder(): Returns a comparator that imposes the reverse of the natural ordering.

nullsFirst(Comparator<T> comparator) and nullsLast(Comparator<T> comparator):

  • Comparator.nullsFirst(): Returns a comparator that considers null values to be less than non-null values, using the specified comparator for non-null values. This means that when you use this comparator to sort a list, null values will appear at the beginning of the sorted list.
  • Comparator.nullsLast(): Returns a comparator that considers null values to be greater than non-null values, using the specified comparator for non-null values. This means that when you use this comparator to sort a list, null values will appear at the end of the sorted list.

comparing(Function<? super T, ? extends U> keyExtractor):

  • Returns a comparator that compares objects based on a key extracted by the provided function.

Comparator<String> byLength = Comparator.comparing(String::length);

comparingInt(ToIntFunction<? super T> keyExtractor)comparingLong(ToLongFunction<? super T> keyExtractor), and comparingDouble(ToDoubleFunction<? super T> keyExtractor):

Provide specialized comparators for primitive data types

Now, let’s begin with the problems.

  1. Sort the strings based on their length in ascending order.

2. Sort the list of integers in descending order and print the result.

3. Sort the list of employees based on their age in ascending order and print the result.

4. Sort the list of employees based on their age in ascending order. If the ages are the same, compare by salary. Print the result.

5. Sort the list of strings based on the index of the first occurrence of “e” in each string and print the result.

6. Sort a list of strings, ignoring case sensitivity, using a case-insensitive comparator.

7. Sort a list of dates in ascending order using the comparing() method with a lambda expression.

8. Sort a list of strings, placing null values at the end.

9. Sort a list of students first by grade in ascending order and then by age in descending order.


Java Streams?

 

You don’t know Java Streams in-practice , Do You?


If you’re not familiar with Java Streams, it is a powerful tool introduced Java 8 onwards, that can help you write more concise, readable, and efficient code. It is also a great way to learn about functional programming concepts.

I know Java Streams can be a bit daunting at first, but I created this article to help you get started. I’ll walk you through 15 coding questions that should help you deal with Java Streams.

By the end of this article, you’ll be able to:

  • Use Streams to solve common problems as a beginner
  • Write more concise and readable code
  • Have a good revision of Streams if you are an experienced developer.

If you are looking for in-depth understanding of Java Streams + LIVE code demo I have a 2-part video series, check out the links below:

Relevant code links — https://github.com/VarshaDas/Java-Code-Snippets/tree/main/LambdasAndStreams/src/main/java

Now let’s start with the 15 Streams-based questions and their code snippets.

1. Find the sum of all even numbers in a list of integers.

2. Find and print the count of strings that have length greater than 5.

3. Implement a function that takes a list of integers as input and returns a new list containing the square of each element.

4. Find the maximum element in a list of integers.

5. Concatenate all the strings in a list into a single string.

6. Convert each string to uppercase and then sort them in alphabetical order.

7. Find the average of all the numbers in a list of doubles using Streams.

8. Create a new list that contains only unique words (remove duplicates).

9. Check if all elements in a List satisfy a given condition using streams.

10. Check if a list contains a specific element using streams.

11. Find the longest string in a list using streams.

12. Remove null values from a list using streams.

13. Problem Statement: GROUP BY Department and Find Max Salary

You have been tasked with analyzing a dataset of employee information to determine the maximum salary in each department. The dataset consists of a list of Employee objects, where each employee has a name, department, and salary. You need to group the employees by their respective departments and identify the maximum salary within each department.

14. Find Second Smallest Element in a List

15. Find Intersection of Two Lists