Here is how to do it as you required. Once the comparator is defined, just sort on the sublist
starting with list 1, skipping over the headings. Since it is a view of the original list it still sorts the required items.
First make a field map on which field to sort. You can make this case insensitive if you want. For this example, case is important.
static Map<String, Integer> sortingFields = new HashMap<>();
static {
List<String> columns = List.of("Name", "Age", "Salary");
for (int i = 0; i < columns.size(); i++) {
sortingFields.put(columns.get(i), i);
}
}
create the list of lists.
List<List<String>> data = new ArrayList<>();
data.add(new ArrayList<>(List.of("Name" ,"Age", "Salary")));
data.add(new ArrayList<>(List.of("Lim", "20", "4000")));
data.add(new ArrayList<>(List.of("Tan", "20", "3000")));
data.add(new ArrayList<>(List.of("Mah", "19", "2500")));
data.add(new ArrayList<>(List.of("Roger", "10", "3500")));
Now invoke the sort and print
sort("Age", data);
data.forEach(System.out::println);
Prints
[Name, Age, Salary]
[Roger, 10, 3500]
[Mah, 19, 2500]
[Lim, 20, 4000]
[Tan, 20, 3000]
Here is the sort method.
public static void sort(String Column, List<List<String>> data) {
// use the column string to select the column number to sort.
Comparator<List<String>> comp =
(a, b) -> a.get(sortingFields.get(column))
.compareTo(b.get(sortingFields.get(column)));
data.subList(1,data.size()).sort(comp);
}
And here is how I would recommend you organize your data and do the sorting.
First create a class as shown. Then populate the list with instances of the class using the data. Then simply specify the getter to sort on. You can add as many additional fields and their getters as required.
The reason is that it allows mixed types to be stored in the same object and still be sorted. If you sort on a String number
it will sort lexcally
rather than numerically
. This will be a problem unless you convert to an integer (to see this, change 4000
to 400
and sort on salary above). But if you want to sort on the name, you would need a different comparator since converting a non-int to an int will throw an exception. This could all be mitigated to some degree but it isn't as straight forward as creating a class.
By simply changing the method reference to the desired getter
you can sort the List
on any field. If no getter is present, and the field is public (not recommended) you can use a lambda.
public class SortingByColumn {
public static void main(String[] args) {
List<Person> data = new ArrayList<>();
data.add(new Person("Lim", 20, 2000));
data.add(new Person("Tan", 20, 3000));
data.add(new Person("Mah", 19, 2500));
data.add(new Person("Roger", 10, 4000));
List<Person> sorted = data.stream()
.sorted(Comparator.comparing(Person::getAge))
.collect(Collectors.toList());
System.out.printf("%10s %10s %10s%n", "Name","Age","Salary");
sorted.forEach(System.out::println);
}
static class Person {
private String name;
private int age;
private int salary;
public Person(String name, int age, int salary) {
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public int getSalary() {
return salary;
}
@Override
public String toString() {
return String.format("%10s %10s %10s", name, age,
salary);
}
}
}
Prints
Name Age Salary
Roger 10 4000
Mah 19 2500
Lim 20 2000
Tan 20 3000