Ordenar um array bidimensional baseado em uma coluna

Em Java, eu tenho um dado no meu array como o seguinte

2009.07.25 20:24 Message A 2009.07.25 20:17 Message G 2009.07.25 20:25 Message B 2009.07.25 20:30 Message D 2009.07.25 20:01 Message F 2009.07.25 21:08 Message E 2009.07.25 19:54 Message R 

Eu gostaria de classificá-lo com base na primeira coluna, para que meus dados finais possam se parecer com isso

 2009.07.25 19:54 Message R 2009.07.25 20:01 Message F 2009.07.25 20:17 Message G 2009.07.25 20:24 Message A 2009.07.25 20:25 Message B 2009.07.25 20:30 Message D 2009.07.25 21:08 Message E 

A primeira coluna é uma data do formato “aaaa.MM.dd HH: mm” e a segunda coluna é uma Sequência.

Ordenar um array bidimensional baseado em uma coluna
A primeira coluna é uma data do formato “aaaa.MM.dd HH: mm” e a segunda coluna é uma Sequência.

Como você diz array 2-D, eu assumo “data do formato …” significa String. Aqui está o código para ordenar uma matriz 2-D de String [] []:

 import java.util.Arrays; import java.util.Comparator; public class Asdf { public static void main(final String[] args) { final String[][] data = new String[][] { new String[] { "2009.07.25 20:24", "Message A" }, new String[] { "2009.07.25 20:17", "Message G" }, new String[] { "2009.07.25 20:25", "Message B" }, new String[] { "2009.07.25 20:30", "Message D" }, new String[] { "2009.07.25 20:01", "Message F" }, new String[] { "2009.07.25 21:08", "Message E" }, new String[] { "2009.07.25 19:54", "Message R" } }; Arrays.sort(data, new Comparator() { @Override public int compare(final String[] entry1, final String[] entry2) { final String time1 = entry1[0]; final String time2 = entry2[0]; return time1.compareTo(time2); } }); for (final String[] s : data) { System.out.println(s[0] + " " + s[1]); } } } 

Saída:

 2009.07.25 19:54 Message R 2009.07.25 20:01 Message F 2009.07.25 20:17 Message G 2009.07.25 20:24 Message A 2009.07.25 20:25 Message B 2009.07.25 20:30 Message D 2009.07.25 21:08 Message E 
 class ArrayComparator implements Comparator { private final int columnToSort; private final boolean ascending; public ArrayComparator(int columnToSort, boolean ascending) { this.columnToSort = columnToSort; this.ascending = ascending; } public int compare(Comparable[] c1, Comparable[] c2) { int cmp = c1[columnToSort].compareTo(c2[columnToSort]); return ascending ? cmp : -cmp; } } 

Dessa forma, você pode manipular qualquer tipo de dados nessas matrizes (contanto que sejam Comparáveis) e você pode classificar qualquer coluna em ordem crescente ou decrescente.

 String[][] data = getData(); Arrays.sort(data, new ArrayComparator(0, true)); 

PS: certifique-se de verificar ArrayIndexOutOfBounds e outros.

EDIT: A solução acima só seria útil se você é capaz de armazenar um java.util.Date na primeira coluna ou se o formato de data permite que você use a comparação simples de String para esses valores . Caso contrário, você precisará converter essa Cadeia em uma Data e poderá conseguir isso usando uma interface de retorno de chamada (como uma solução geral). Aqui está uma versão aprimorada:

 class ArrayComparator implements Comparator { private static Converter DEFAULT_CONVERTER = new Converter() { @Override public Comparable convert(Object o) { // simply assume the object is Comparable return (Comparable) o; } }; private final int columnToSort; private final boolean ascending; private final Converter converter; public ArrayComparator(int columnToSort, boolean ascending) { this(columnToSort, ascending, DEFAULT_CONVERTER); } public ArrayComparator(int columnToSort, boolean ascending, Converter converter) { this.columnToSort = columnToSort; this.ascending = ascending; this.converter = converter; } public int compare(Object[] o1, Object[] o2) { Comparable c1 = converter.convert(o1[columnToSort]); Comparable c2 = converter.convert(o2[columnToSort]); int cmp = c1.compareTo(c2); return ascending ? cmp : -cmp; } } interface Converter { Comparable convert(Object o); } class DateConverter implements Converter { private static final DateFormat df = new SimpleDateFormat("yyyy.MM.dd hh:mm"); @Override public Comparable convert(Object o) { try { return df.parse(o.toString()); } catch (ParseException e) { throw new IllegalArgumentException(e); } } } 

E neste ponto, você pode classificar sua primeira coluna com:

 Arrays.sort(data, new ArrayComparator(0, true, new DateConverter()); 

Eu pulei as verificações de nulos e outros problemas de tratamento de erros.

Eu concordo que isso já está começando a parecer uma estrutura. 🙂

Última (espero) edição: Eu só agora percebo que o formato de data permite que você use comparação simples String. Se for esse o caso, você não precisa da “versão aprimorada”.

 Arrays.sort(yourarray, new Comparator() { public int compare(Object o1, Object o2) { String[] elt1 = (String[])o1; String[] elt2 = (String[])o2; return elt1[0].compareTo(elt2[0]); } }); 

Supondo que sua matriz contenha strings, você pode usar o seguinte:

 String[] data = new String[] { "2009.07.25 20:24 Message A", "2009.07.25 20:17 Message G", "2009.07.25 20:25 Message B", "2009.07.25 20:30 Message D", "2009.07.25 20:01 Message F", "2009.07.25 21:08 Message E", "2009.07.25 19:54 Message R" }; Arrays.sort(data, new Comparator() { @Override public int compare(String s1, String s2) { String t1 = s1.substring(0, 16); // date/time of s1 String t2 = s2.substring(0, 16); // date/time of s2 return t1.compareTo(t2); } }); 

Se você tem uma matriz bidimensional, a solução também é muito semelhante:

 String[][] data = new String[][] { { "2009.07.25 20:17", "Message G" }, { "2009.07.25 20:25", "Message B" }, { "2009.07.25 20:30", "Message D" }, { "2009.07.25 20:01", "Message F" }, { "2009.07.25 21:08", "Message E" }, { "2009.07.25 19:54", "Message R" } }; Arrays.sort(data, new Comparator() { @Override public int compare(String[] s1, String[] s2) { String t1 = s1[0]; String t2 = s2[0]; return t1.compareTo(t2); } }); 
  1. instalar o java8 jdk + jre

  2. use a expressão lamda para classificar o array 2D .

código:

 import java.util.Arrays; import java.util.Comparator; class SortString { public static void main(final String[] args) { final String[][] data = new String[][] { new String[] { "2009.07.25 20:24", "Message A" }, new String[] { "2009.07.25 20:17", "Message G" }, new String[] { "2009.07.25 20:25", "Message B" }, new String[] { "2009.07.25 20:30", "Message D" }, new String[] { "2009.07.25 20:01", "Message F" }, new String[] { "2009.07.25 21:08", "Message E" }, new String[] { "2009.07.25 19:54", "Message R" } }; // this is applicable only in java 8 version. Arrays.sort(data, (String[] s1, String[] s2) -> s1[0].compareTo(s2[0])); // we can also use Comparator.comparing and point to Comparable value we want to use // Arrays.sort(data, Comparator.comparing(row->row[0])); for (final String[] s : data) { System.out.println(s[0] + " " + s[1]); } } } 

saída

 2009.07.25 19:54 Message R 2009.07.25 20:01 Message F 2009.07.25 20:17 Message G 2009.07.25 20:24 Message A 2009.07.25 20:25 Message B 2009.07.25 20:30 Message D 2009.07.25 21:08 Message E 

Confira o ColumnComparator . É basicamente a mesma solução proposta por Costi, mas também suporta a sorting em colunas em uma lista e tem mais algumas propriedades de sorting.

Usando Lambdas desde o java 8:

 final String[][] data = new String[][] { new String[] { "2009.07.25 20:24", "Message A" }, new String[] { "2009.07.25 20:17", "Message G" }, new String[] { "2009.07.25 20:25", "Message B" }, new String[] { "2009.07.25 20:30", "Message D" }, new String[] { "2009.07.25 20:01", "Message F" }, new String[] { "2009.07.25 21:08", "Message E" }, new String[] { "2009.07.25 19:54", "Message R" } }; String[][] out = Arrays.stream(data).sorted(Comparator.comparing(x -> x[1])).toArray(String[][]::new); System.out.println(Arrays.deepToString(out)); 

Saída:

[[2009.07.25 20:24, Mensagem A], [2009.07.25 20:25, Mensagem B], [2009.07.25 20:30, Mensagem D], [2009.07.25 21:08, Mensagem E], [ 2009.07.25 20:01, Mensagem F], [2009.07.25 20:17, Mensagem G], [2009.07.25 19:54, Mensagem R]]