Home > Blockchain >  How can I loop through and Sort a nested List based on the First element of each sub-Lists
How can I loop through and Sort a nested List based on the First element of each sub-Lists

Time:05-19

For example:

 a = [jamie, 3, 5, NY]`

 b = [Barney, 2, 3, FL]

 c = [Thomas, 4, 6, TX]

 d = [Darnell, 5, 6, NC]

unsortedArrayList = [ [jamie, 3, 5, NY], [Barney, 2, 3, FL], [Thomas, 4, 6, TX], [Darnell, 5, 6, NC] ]

I want to loop through the unsortedArrayList input and sort it by the first element of each sub-list such that the output will be:

sortedArrayList = [ [Barney, 2, 3, FL], [Darnell, 5, 6, NC], [jamie, 3, 5, NY], [Thomas, 4, 6, TX] ]

so far, I have looped through the unsorted list:

for(ArrayList<String> s : unsortedList)

How can I implement sorting?

I would greatly appreciate any clearly written out implementations on how to sort this list, because I'm not exactly sure how to go about it.

CodePudding user response:

If you want to sort the original list (which means everything in your list will be in a different place and you lose the original order) then use the sort method:

unsortedArrayList.sort((a, b) -> a.get[0].compareTo(b.get(0)));

If you want to create a new sorted list, leaving the original list unchanged:

var sortedList = new ArrayList<>(unsortedArrayList);
sortedList.sort((a, b) -> a.get[0].compareTo(b.get(0)));

or use Streams:

var sortedList = unsortedArrayList.stream()
    .sorted((a, b) -> a.get[0].compareTo(b.get(0)))
    .toList();

In each case, the argument to the sort or sorted method is a Comparator which takes the two sublist arguments and compares the first element of each.

CodePudding user response:

Everything you need to solve this problem is to define a comparator that will establish the order of lists of String based on the first element and comparison should be case-insensitive (because you've specified in the example that "jamie" should appear before "Thomas").

The fluent way to define a comparator is to make use of static methods introduced with Java 8, in this case we can utilize comparing(function, Comparator):

Comparator<List<String>> comparator = 
    Comparator.comparing(list -> list.get(0), String.CASE_INSENSITIVE_ORDER);

The first argument keyExtractor function defines how to extract to extract the sorting key from the given element. And the second argument denotes the comparator that needs to be used to compare the key, in this comparator CASE_INSENSITIVE_ORDER accessible as a static field in the String class.

For more information on how to build Comparators using Java 8 method have a look at this tutorial.

You can also define this comparator inline (it depends on how frequently it'll be required to sort the incoming lists). And if it's not necessary to preserve the initial form of the unsorted list, it could be done by applying method sort() (also added with Java 8) on the list:

unsorted.sort(Comparator.comparing(list -> list.get(0), String.CASE_INSENSITIVE_ORDER));
    
System.out.println(unsorted);

Will produce the output:

[[Barney, 2, 3, FL], [Darnell, 5, 6, NC], [jamie, 3, 5, NY], [Thomas, 4, 6, TX]]

Otherwise, if you need to preserve the unsorted list intact, you can create a copy of the list sort it as shown above or you can make use of Stream API to generate a new sorted list:

List<List<String>> sortedByFirstElement = unsorted.stream()
    .sorted(Comparator.comparing(list -> list.get(0), String.CASE_INSENSITIVE_ORDER))
    .collect(Collectors.toList()); // or .toList() with Java 16 

Will give the output:

[[Barney, 2, 3, FL], [Darnell, 5, 6, NC], [jamie, 3, 5, NY], [Thomas, 4, 6, TX]]

Have a look at these tutorials provided by Oracle for more information on lambda expressions and streams.

You play around with this Demo Online.

Sidenote: it seems like each list contains the personal data. If so consider defining a class (like Person, or Employee, etc.), because storing the object data in a collection is an antipattern. Classes provide a structure to the data, ability to use appropriate types for each value, and convenient access via methods with self-explanatory names instead of faceless get(0).

  • Related