2016-05-03 27 views
5

Pracuję więc nad funkcją szukania szerokości do pierwszego dla programu, nad którym pracuję dla szkoły, i kiedy przechodzę przez krawędzie wychodzące dla danego węzła, z racji tego, w jaki sposób przechodzę przez moje możliwe krawędzie , wygląda mniej więcej tak:Jak mogę posortować ArrayList <ArrayList <String>>?

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

Ale to, co naprawdę chcę to:

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

Gdzie pierwszy indeks pary to nazwa węzła, że ​​punkty edge oraz drugi indeks to etykieta krawędzi. Zasadniczo chcę przejść przez te krawędzie alfabetycznie, najpierw przez nazwę węzła, a następnie przez nazwę etykiety, ale nie jestem pewien, jak to zrobić, ponieważ Collections.sort() nie działa dla 2D ArrayList. Jakieś wskazówki/pomysły dotyczące dobrej metody sortowania tego? Dziękuję wszystkim!

EDIT: używam JRE 1.7 dla tego zadania, a nie 1,8

+0

'[[A, 1], [D, 1], [C, 2], [D, 2]] 'nie jest poprawnym przykładem dla' ArrayList > ' Można użyć' .stream(). Sorted() 'aby sortować według porządku naturalnego lub nawet zdefiniować custom 'Comparator' –

+0

Możesz użyć HashMap zamiast ArrayList ... – RoiEX

+1

RoiEX, nie może używać HashMap, ponieważ może mieć klucz o różnych wartościach lub musi być HashMap ... to tworzy dość skomplikowaną strukturę na coś prostego. – jeorfevre

Odpowiedz

2

tutaj jest kompletny kod roboczych. Praca z wyrażeniem lambda w java SDK8.

Jak zobaczysz, dodałem prostą klasę i komparator. To jest proste i potężne.

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 wyjście

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

2

@jeorfevre odpowiedź jest całkowicie w porządku. Nie wspomniałeś o wersji Java, ale skorzystałbym ze sposobów statycznych: Comparator.

Rozwiązaniem będzie deklaratywne i daje większą kontrolę i przejrzystość w zwięzły sposób:

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

Jeśli chcesz odwrócić kolejność:

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

daje:

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

I

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

wyjściowy: [[D, 1], [D 2], [C-2], [A 1]]

+0

To wygląda świetnie! Dokładnie to, co myślałem o implementacji (klasa Edge), daje mi trochę więcej perspektywy na to, jak powinienem zarządzać swoimi krawędziami. Moje następne pytanie brzmi: skoro pracuję z tymi krawędziami nie wewnątrz klasy Edge, ale w zupełnie innej klasie, gdzie chciałbym umieścić komparator? Czy wejdzie on w jakąkolwiek funkcję, z którą obecnie pracuję?Przepraszam, jestem stosunkowo nowy w Javie i bardzo nowy w komparatorach. –

+0

Mam również problem z komendami Edge :: getName i Edge :: getLabel, ponieważ dla tego zadania mój profesor chce, abyśmy używali JRE 1.7, a nie 1.8. Czy istnieje inny sposób implementacji tego przy użyciu JRE 1.7? –

Powiązane problemy