Sorting a list of lists using a comparator

I am viewing a list of lists (in ArrayLists) using a comparator. Where is the first order. All capital letters will always be the same size.

For example, a list

[[4,5,6], [7,9,10], [4,7,8], [1,2,3], [7,9,12]]

It must

[[7,9,12], [7,9,10], [4,7,8], [4,5,6], [1,2,3]]

I have something like this, but only sorted by the first item in each list

List<List<Integer>> list = Arrays.asList(
                Arrays.asList(4,5,6),
                Arrays.asList(7,9,10), 
                Arrays.asList(4,7,8),
                Arrays.asList(1,2,3), 
                Arrays.asList(7,9,12));

list.sort((l1, l2) -> l2.get(0).compareTo(l1.get(0)));

What produces:

[[7, 9, 10], [7, 9, 12], [4, 5, 6], [4, 7, 8], [1, 2, 3]]

How can I write a comparator that sorts by the next element in the list if the before element is equal?

For example, [7, 9, 10], [7, 9, 12] should go to a comparison of two 7, then two 9, and then 10 and 12. For example, [4, 5, 6] [4, 7, 8] must go to compare two 4, and then 4 and 7 and stop.

+4
source share
4 answers

You can define a comparator as such:

Comparator<List<Integer>> comparator = (list1, list2) -> {
       for (int i = 0; i < list1.size(); i++) {
            int value = Integer.compare(list2.get(i), list1.get(i));
            if (value != 0)
                return value;
       }
       return 0;
};

or

Comparator<List<Integer>> comparator = (list1, list2) -> 
IntStream.range(0, list1.size())
         .map(i -> Integer.compare(list2.get(i), list1.get(i)))
         .filter(value -> value != 0)
         .findFirst()
         .orElse(0);

:

list.sort(comparator);

, , i.e.:

static <T extends Comparable<T>> Comparator<List<T>> comparator(){
       return (o1, o2) -> IntStream.range(0, o1.size())
                                   .map(i -> o2.get(i).compareTo(o1.get(i)))
                                   .filter(value -> value != 0)
                                   .findFirst()
                                   .orElse(0);
}

:

List<List<Integer>> integerList = Arrays.asList(
                Arrays.asList(4,5,6),
                Arrays.asList(7,9,10),
                Arrays.asList(4,7,8),
                Arrays.asList(1,2,3),
                Arrays.asList(7,9,12));

integerList.sort(comparator()); // sort list of integers descending

List<List<String>> stringList = Arrays.asList(
                Arrays.asList("a","b","c"),
                Arrays.asList("d","e","f"),
                Arrays.asList("g","h","i"));

stringList.sort(comparator()); // sort list of strings descending 

..

. JDK 9+, , JDK 8.

+3

, , , , :

Comparator<Integer> intReversed = Integer::compare;
intReversed = intReversed.reversed(); // integer reversed order comparator

// Chain comparators for 3 indices (could also do this in a loop for lists of unknown size)
// Each step compares the extracted element using the given comparator:
Comparator<List<Integer>> comp = Comparator.comparing(l -> l.get(0), intReversed);
comp = comp.thenComparing(l -> l.get(1), intReversed);
comp = comp.thenComparing(l -> l.get(2), intReversed);

list.sort(comp);        
System.out.println(list); // [[7, 9, 12], [7, 9, 10], [4, 7, 8], [4, 5, 6], [1, 2, 3]]
+1

, , .

, . , . , .

, ​​ :

private static <T> int compareLexicographically(
    List<? extends T> list0,
    List<? extends T> list1, 
    Comparator<? super T> comparator)

. Integer ( , Comparable), Comparator#naturalOrder , . , , .

, , Integer, String ( Person, getName).

import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

public class LexicographicalComparator
{
    public static void main(String[] args)
    {
        exampleWithIntegers();
        exampleWithStrings();
        exampleWithPersons();
    }

    private static void exampleWithIntegers()
    {
        List<List<Integer>> list = Arrays.asList(
            Arrays.asList(4, 5, 6), 
            Arrays.asList(7, 9, 10),
            Arrays.asList(4, 7, 8), 
            Arrays.asList(1, 2, 3),
            Arrays.asList(7, 9, 12));

        Comparator<List<Integer>> comparator = lexicographicalComparator();
        list.sort(comparator.reversed());

        System.out.println("Integers, descending:");
        list.forEach(System.out::println);
    }

    private static void exampleWithStrings()
    {
        List<List<String>> list = Arrays.asList(
            Arrays.asList("B", "B", "C"), 
            Arrays.asList("C", "B", "B"),
            Arrays.asList("B", "C", "A"), 
            Arrays.asList("A", "C", "B"),
            Arrays.asList("C", "B", "A"));

        Comparator<List<String>> comparator = lexicographicalComparator();
        list.sort(comparator);

        System.out.println("Strings, ascending:");
        list.forEach(System.out::println);
    }

    private static void exampleWithPersons()
    {
        class Person 
        {
            String name;
            Person(String name)
            {
                this.name = name;
            }
            String getName()
            {
                return name;
            }

            @Override
            public java.lang.String toString()
            {
                return name;
            }
        }

        List<List<Person>> list = Arrays.asList(
            Arrays.asList(new Person("B"), new Person("B"), new Person("C")), 
            Arrays.asList(new Person("C"), new Person("B"), new Person("B")),
            Arrays.asList(new Person("B"), new Person("C"), new Person("A")), 
            Arrays.asList(new Person("A"), new Person("C"), new Person("B")),
            Arrays.asList(new Person("C"), new Person("B"), new Person("A")));

        Comparator<List<Person>> comparator = 
            lexicographicalComparator(Comparator.comparing(Person::getName));
        list.sort(comparator);

        System.out.println("Persons, by name, ascending:");
        list.forEach(System.out::println);
    }



    private static <T extends Comparable<? super T>> Comparator<List<T>> 
        lexicographicalComparator()
    {
        return (list0, list1) -> 
            compareLexicographically(list0, list1, Comparator.naturalOrder());
    }

    private static <T> Comparator<List<T>> lexicographicalComparator(
        Comparator<? super T> comparator)
    {
        return (list0, list1) -> 
            compareLexicographically(list0, list1, comparator);
    }

    private static <T> int compareLexicographically(
        List<? extends T> list0,
        List<? extends T> list1, 
        Comparator<? super T> comparator)
    {
        if (list0.size() < list1.size())
        {
            return -1;
        }
        if (list0.size() > list1.size())
        {
            return 1;
        }
        for (int i = 0; i < list0.size(); i++)
        {
            T t0 = list0.get(i);
            T t1 = list1.get(i);
            int value = comparator.compare(t0, t1);
            if (value != 0)
            {
                return value;
            }
        }
        return 0;
    }
}

. :

  • , ?
  • , null?

, , .

, Comparator#nullsFirst Comparator#nullsLast, , .

+1

Lists:

list.sort((l1, l2) -> l2.get(0).compareTo(l1.get(0)));

, , , .

List String, :

list.sort((l1, l2) -> l2.toString()
                        .compareTo(l1.toString()));

List String .

0

Source: https://habr.com/ru/post/1695600/


All Articles