2016-05-03 22 views
5

Quindi sto lavorando a una funzione di ricerca di Breadth-First per un programma a cui sto lavorando per la scuola, e quando passo attraverso i bordi in uscita per un dato nodo, in virtù di come sto passando attraverso i miei possibili margini , sembra qualcosa di simile:Come posso ordinare un ArrayList <ArrayList <String>>?

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

Ma quello che voglio veramente è questo:

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

Dove il primo indice di una coppia è il nome del nodo che i punti di bordo a, e la secondo indice è l'etichetta per il bordo. Essenzialmente voglio passare attraverso questi bordi in ordine alfabetico, prima per nome nodo, poi per nome etichetta, ma non sono sicuro di come farlo, dal momento che Collections.sort() non funziona per un ArrayList 2D. Qualche suggerimento/idea su un buon metodo per ordinare questo? Grazie a tutti!

EDIT: Sto usando JRE 1.7 per questo incarico, non 1.8

+0

'[[A, 1], [D, 1], [C, 2], [D, 2]] 'is non è un esempio valido per' ArrayList > ' Puoi usare' .stream(). Sorted() 'per ordinare per ordine naturale o anche definire un custom 'Comparator' –

+0

Puoi usare una HashMap invece di una ArrayList ... – RoiEX

+1

RoiEX, non posso usare HashMap dato che può avere una chiave che ha valori diversi o deve essere una HashMap ... ciò rende una struttura abbastanza complicata per qualcosa di semplice. – jeorfevre

risposta

2

Ecco il codice di lavoro completo. funziona con espressione lambda in java SDK8.

Come vedrete, ho aggiunto una classe semplice e un comparatore. Questo è semplice e potente.

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 uscita

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

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

2

@jeorfevre risposta è perfettamente ok. Non hai menzionato la versione di Java, ma andrei con i metodi statici Comparator.

La soluzione sarà dichiarativa e vi darà un maggiore controllo e chiarezza in maniera succinta:

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); 
    } 
} 

Se volete l'ordine invertito:

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

Ti dà:

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

E

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

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

+0

Sembra fantastico! È esattamente ciò che stavo pensando di implementare (classe Edge) e mi dà un po 'più di prospettiva su come dovrei gestire i miei margini. La mia prossima domanda è, dal momento che sto lavorando con questi bordi non all'interno di una classe Edge, ma in una classe completamente diversa, dove metterei il comparatore? Andrebbe all'interno di qualsiasi funzione con cui sto attualmente lavorando?Mi scuso, sono relativamente nuovo a Java e molto nuovo ai comparatori. –

+0

Inoltre, sto riscontrando un problema con i comandi Edge :: getName e Edge :: getLabel perché per questo compito, il mio professore ci vuole usare JRE 1.7, non 1.8. C'è un altro modo per implementarlo usando JRE 1.7? –