Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I sort an ArrayList<ArrayList<String>>?

So I'm working on a Breadth-First search function for a program I'm working on for school, and when I go through the outgoing edges for a given node, by virtue of how I'm going through my possible edges, it looks something like this:

[[A, 1], [D, 1], [C, 2], [D, 2]]

But what I really want is this:

[[A, 1], [C, 2], [D, 1], [D, 2]]

Where the first index of a pair is the name of the node that the edge points to, and the second index is the label for the edge. Essentially I want to go through these edges alphabetically, first by node name, then by label name, but I'm not sure how to do that, since Collections.sort() doesn't work for a 2D ArrayList. Any pointers/ideas on a good method to sort this? Thanks everyone!

EDIT: I am using JRE 1.7 for this assignment, not 1.8

like image 702
Ethan Fox Avatar asked May 03 '16 18:05

Ethan Fox


2 Answers

here is the complete working code. working with lambda expression in java SDK8.

As you will see, I've added a simple class and a comparator. This is simple and powerful.

package com.rizze.test.labs.sof;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.junit.Test;

public class SOF {    

    public static class Link {
        public String name;
        public int id;

        public static Link build(String n, int i){
            Link l = new Link();
            l.name = n;
            l.id=i;
            return l;
        }

        public String toString(){
            return String.format("[%s , %d]", name,id);
        }           
    }       

    @Test
    public void test() {

        List<Link> links = new ArrayList<Link>();

        //SSETUP [[A, 1], [C, 2], [D, 1], [D, 2]]
        links.add(Link.build("D", 1));
        links.add(Link.build("A", 1));
        links.add(Link.build("D", 2));
        links.add(Link.build("C", 2));


        Collections.sort(links, new Comparator<Link>() {    
            @Override
            public int compare(Link p1, Link p2) {
                int ret = p1.name.compareTo(p2.name);
                if(ret == 0) {
                    ret= p1.id - p2.id;
                }
                return ret;             
            }               
        });
        System.out.println(links);          
    }    
}

//Console output

Before : [[D , 1], [A , 1], [D , 2], [C , 2]]
Sorted: [[A , 1], [C , 2], [D , 1], [D , 2]]

//GIST link https://gist.github.com/jeorfevre/cbcd7dac5d7fabde6a16db83bdfb7ef5

like image 92
jeorfevre Avatar answered Nov 09 '22 13:11

jeorfevre


@jeorfevre answer is perfectly ok. You didn't mention version of Java but I'd go with static Comparator methods.

The solution will be declarative and will give you more control and clarity in a succinct way:

public class Test {
    public static class Edge {
        private String name;
        private int label;
        public Edge(String name, int id) {
            this.name = name;
            this.label = id;
        }
        public String toString() {
            return String.format("[%s , %d]", name, label);
        } 
        public String getName() { return name; } 
        public int getLabel() { return label; }
    }


    public static void main(String[] args) {
        List<Edge> edges = new ArrayList<>();
        edges.add(new Edge("D", 1));
        edges.add(new Edge("A", 1));
        edges.add(new Edge("D", 2));
        edges.add(new Edge("C", 2));

        Comparator<Edge> comparator = Comparator
                .comparing(Edge::getName)
                .thenComparing(Edge::getLabel);

        edges.sort(comparator);

        System.out.println(edges);
    }
}

If you want reversed order:

            Comparator<Edge> comparator = Comparator
                .comparing(Edge::getName)
                .thenComparing(Edge::getLabel)
                .reversed();

Gives you:

[[D , 2], [D , 1], [C , 2], [A , 1]]

And

            Comparator<Edge> comparator = Comparator
                .comparing(Edge::getName)
                .reversed()
                .thenComparing(Edge::getLabel);

output is: [[D , 1], [D , 2], [C , 2], [A , 1]]

like image 2
Xeon Avatar answered Nov 09 '22 15:11

Xeon