长列表排序列表

时间:2021-02-17 02:31:10

标签: java java-8

给定一个ArrayList<ArrayList<Long>>,我们如何根据内部列表的元素对外部列表中的元素(列表)进行排序?

限制条件

  1. 只应排序外部列表。
  2. 不应修改内部列表中元素的顺序。

输入:

[
    [1],
    [2, 5, 6],
    [6, 5],
    [1, 2],
    [2],
    [1, 2, 3],
    [2, 3]
]

预期输出:

    [1],
    [1, 2],
    [1, 2, 3],
    [2],
    [2, 3],
    [2, 5, 6],
    [6, 5]

1 个答案:

答案 0 :(得分:5)

使用元素比较器

比较 2 个列表

  1. 按索引位置的升序进行比较
  2. 如果找到任何非零值,则返回结果
  3. else 比较列表的大小
  4. 使用此比较器逻辑对列表进行排序

使用每个索引比较器链。基于 WJS 的方法

  1. 计算所有内部列表的最大列表大小
  2. 为从 0 到计算出的最大大小的每个索引创建一个比较器链
  3. 使用这个装饰(责任链)比较器对列表进行排序
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.function.IntFunction;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class SortNestedList {

    protected List<List<Long>> transform(Long[][] inputArray) {
        return Arrays.stream(inputArray)
            .filter(Objects::nonNull) // filter outer null lists
            .map(nested -> Arrays.stream(nested)
                .filter(Objects::nonNull)
                .collect(Collectors.toList())) // generate nested list by filtering any null values
            .collect(Collectors.toList());
    }

    protected void sortWithElementComparator(List<List<Long>> lists) {
        lists.sort((a, b) -> {
            return IntStream.range(0, Math.min(a.size(), b.size())) // check till end of minimum sized list
                .map(i -> Long.compare(a.get(i), b.get(i))) // compare elements at same index
                .filter(i -> i != 0) // ignore equal values comparison
                .findFirst() // get first non-zero comparison result (unequal)
                .orElse(Integer.compare(a.size(), b.size())); // if nothing, then compare size
        });

        lists.forEach(System.out::println);
    }

    protected void sortWithDecoratedComparator(List<List<Long>> lists) {
        // comparator for an index
        IntFunction<Comparator<List<Long>>> elementAtIndexComparator =
            index -> (a, b) -> index < Math.min(a.size(), b.size()) ?
                Long.compare(a.get(index), b.get(index)) : // compare elements if index is valid for both lists
                Integer.compare(a.size(), b.size()); // compare size if index is invalid for atleast 1 list

        final int maxInnerIndices = lists.stream()
            .mapToInt(List::size)
            .max().orElse(0); // get max inner list size or 0 if empty

        Comparator<List<Long>> listComparator = IntStream.range(0, maxInnerIndices)
            .mapToObj(elementAtIndexComparator) // index comparator for every index
            .reduce(Comparator::thenComparing) // kind of chain of responsibility / decorator
            .orElse((a, b) -> 0);

        lists.sort(listComparator);

        lists.forEach(System.out::println);
    }

    protected void sort(Long[][] inputArray, int run) {
        System.out.println("Sort input using direct element comparator: " + run);
        sortWithElementComparator(transform(inputArray));
        System.out.println("Sort input using decorated comparator: " + run);
        sortWithDecoratedComparator(transform(inputArray));
    }
}

测试代码

    public static void main(String[] args) {
        final SortNestedList sortNestedList = new SortNestedList();
        int run = 0;

        Long[][] inputArray = new Long[][]{};
        sortNestedList.sort(inputArray, ++run);

        inputArray = new Long[][]{{null}};
        sortNestedList.sort(inputArray, ++run);

        inputArray = new Long[][]{{null}, {1L}};
        sortNestedList.sort(inputArray, ++run);

        inputArray = new Long[][]{null, {1L}};
        sortNestedList.sort(inputArray, ++run);

        inputArray = new Long[][]{{1L}, {1L}};
        sortNestedList.sort(inputArray, ++run);

        inputArray = new Long[][]{{2L}, {1L}};
        sortNestedList.sort(inputArray, ++run);

        inputArray = new Long[][]{{2L, 1L}, {1L, 3L}};
        sortNestedList.sort(inputArray, ++run);

        inputArray = new Long[][]{{Long.MAX_VALUE, 1L}, {Long.MIN_VALUE, 3L}};
        sortNestedList.sort(inputArray, ++run);

        inputArray = new Long[][]{{1L}, {2L, 5L, 6L},
            {1L, 2L}, {2L}, {1L, 2L, 3L}, {3L, 2L}, {2L, 3L},
            {1L, 2L, 3L, 4L, 6L}, {1L, 2L, 3L, 4L, 5L},
            {1L, 2L, 3L, 4L, 6L, 2L}, {1L, 2L, 3L, 4L, 5L, 3L, 5L},
            {Long.MAX_VALUE, Long.MAX_VALUE, 1L, 5L, Long.MIN_VALUE + 1, Long.MAX_VALUE - 1},
            {Long.MAX_VALUE, Long.MIN_VALUE, 1L, 5L, Long.MIN_VALUE + 1, Long.MAX_VALUE - 1},
            {Long.MIN_VALUE}, {Long.MAX_VALUE}};
        sortNestedList.sort(inputArray, ++run);
    }

感谢 Holger 和 WJS

相关问题