Home > Software design >  Find Common element in two lists in java and add them to starting position in list with remaining el
Find Common element in two lists in java and add them to starting position in list with remaining el

Time:12-30

I have two lists containing names. The first list l1 has selected names, and the second list l2 has all the names.

Example:

List<String> l1 = {"en", "cu", "eu"};
List<String> l2 = {"ch", "cu", "en", "eu", "pe"};

All the elements in l1 always exist in l2.

I want to obtain the output where all the common names are placed at the beginning followed by the remaining names, and I need them to be sorted in the ascending order. Like this:

output ->  {cu, en, eu, ch, pe};

What I was trying to do I've shown below, but don't getting the idea that how to place common elements at the starting position (2nd list is already sorted) and place the remaining elements after the common elements

List<String> common = l2.stream().filter(l2::contains).collect(Collectors.toList());

CodePudding user response:

If I understood correctly, you want to sort the elements from the second list l2 by placing the values that are present in the first list l1 at the beginning, and both part should be sorted in the alphabetical order.

You need to define a custom Comparator for that purpose. Since Java 8 the recommended way to create a Comparator is to use static factory methods like Comparator.comparing().

While implementing the Comparator, firstly we need to check if a particular value is present in the first list and order the elements by the result of this check (reminder: natural ordering of boolean values is false -> true). And since contains() on a list is costful (it does iteration over the list under the hood and therefore runs in O(n)) it would be performance-wise to dump the data from the first list into a HashSet and perform checks against this Set.

The in order to sort both parts of the list alphabetically, we need can chain the second comparator by applying Comparator.thenComparing() and providing Comparator.naturalOrder() as the argument.

Here's how it might be implemented:

List<String> l1 = List.of("en", "cu", "eu");
List<String> l2 = List.of("ch", "cu", "en", "eu", "pe");
        
// output ->  {cu,en,eu,cu,pe};
        
Set<String> toCheck = new HashSet<>(l1);
Comparator<String> comparator =
    Comparator.<String,Boolean>comparing(toCheck::contains).reversed()
        .thenComparing(Comparator.naturalOrder());
        
List<String> sorted = l2.stream()
    .sorted(comparator)
    .toList(); // for Java 16 or collect(Collectors.toList())
    
System.out.println(sorted);

Output:

[cu, en, eu, ch, pe]
  • Related