Regexes
Regexes

Reputation: 105

Sorting a 2D arraylist in Java with different lengths of 1D lists

I have been trying to lexicographically sort a 2D ArrayList using a custom Comparator. But the lengths of every single 1D lists are different so I am not getting the expected result here is my code:

List<ArrayList<Integer>> a = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> a1 = new ArrayList<Integer>();
ArrayList<Integer> a2 = new ArrayList<Integer>();
ArrayList<Integer> a3 = new ArrayList<Integer>();
ArrayList<Integer> a4 = new ArrayList<Integer>();

a1.add(1);

a2.add(1);
a2.add(3);

a3.add(1);
a3.add(2);
a3.add(3);

a.add(a1);
a.add(a2);
a.add(a3);

Collections.sort(a, new Comparator<ArrayList<Integer>>() {
    @Override
    public int compare(ArrayList<Integer> a, ArrayList<Integer> b) {
        if (a.get(0) < b.get(0))
            return 1;
        return -1;
    }
});
System.out.println(a);

So the input is [[1], [1, 3], [1, 2, 3]]

My output is [[1, 2, 3], [1, 3], [1]]

The expected output is [[1],[1,2,3],[1,3]]

Please point out the errors and the additions required to make the code work

Upvotes: 1

Views: 534

Answers (3)

It seems you need lexicographical ordering. Guava library has utility method which could help you:

import com.google.common.collect.Comparators;
...
Collections.sort(a, Comparators.lexicographical(Comparator.naturalOrder()));

Upvotes: 1

dariosicily
dariosicily

Reputation: 4527

You are trying to define a custom Comparator sorting your 2d integer ArrayList comparing the two String representations of two 1d ArrayList: for example with ArrayList [1] and [1, 3] you will compare the strings "1" and "13". This can be obtained using the streams and String.valueOf methods like below , I assume you have no empty integer ArrayList:

Collections.sort(a, new Comparator<List<Integer>>() {
    @Override
    public int compare(List<Integer> a, List<Integer> b) {
        String j1 = a.stream().map(String::valueOf).collect(Collectors.joining(""));
        String j2 = b.stream().map(String::valueOf).collect(Collectors.joining(""));

        return j1.compareTo(j2);
    }
});

This will produce your expected ordered output.

Upvotes: 1

Eritrean
Eritrean

Reputation: 16498

First determine which of the lists to be compared is the shorter one. You can determine this for example using the method Math.min(int a, int b). Then compare each element of the first list with the corresponding element of the second list. If they are not equal, return the result of this comparison. If all are equal, compare the length of the lists and return this value.

List<List<Integer>> listOfLists = new ArrayList<>();
List<Integer> listOne = new ArrayList<>();
listOne.add(1);

List<Integer> listTwo = new ArrayList<>();
listTwo.add(1);
listTwo.add(2);
listTwo.add(3);

List<Integer> listThree = new ArrayList<>();
listThree.add(1);
listThree.add(3);

listOfLists.add(listOne);
listOfLists.add(listTwo);
listOfLists.add(listThree);
    
Collections.sort(listOfLists, new Comparator<List<Integer>>() {
    @Override
    public int compare(List<Integer> first, List<Integer> second) {
        int comp = 0;
        for(int i = 0; i < Math.min(first.size(), second.size()); i++){
            comp = Integer.compare(first.get(i), second.get(i));
            if(comp != 0){
                return comp;
            }
         }
         return Integer.compare(first.size(), second.size());
    }
});
System.out.println(listOfLists);

Upvotes: 2

Related Questions