Structure de données java de type table


J'ai besoin d'implémenter une sorte de structure de données de type table qui stocke des informations comme celle-ci en Java:

+--------+-------+-----+
|  sij   |   i   |  j  |
+--------+-------+-----+
|   45   |   5   |  7  |
+--------+-------+-----+ 
|   33   |   1   |  6  |
+--------+-------+-----+ 
|   31   |   0   |  9  |
+--------+-------+-----+ 
|   12   |   8   |  2  |
+--------+-------+-----+ 

Et je dois pouvoir trier la table par le paramètre sij. J'ai fait quelques tests avec ArrayList et HashMap, mais je ne peux pas les faire fonctionner correctement.

Author: Brian Tompsett - 汤莱恩, 2009-11-07

7 answers

Il est un générique TreeBasedTable classe de Google goyave bibliothèque qui fait exactement ce que vous demandez. Il offre également de nombreuses autres méthodes utilitaires utiles et son utilisation est indiquée dans le guide de l'utilisateur .

Des documents TreeBasedTable:

Implémentation de Table dont les clés de ligne et les clés de colonne sont ordonnées par leur ordre naturel ou par des comparateurs fournis.

Exemple d'utilisation:

RowSortedTable<Vertex, Vertex, Double> weightedGraph = TreeBasedTable.create();
weightedGraph.put(v2, v3, 4.0);
weightedGraph.put(v1, v2, 20.0);

System.out.println( weightedGraph.rowKeySet() ); // prints [v1, v2]
 23
Author: Andrejs, 2017-07-07 18:59:31

Que voulez vous dire par:

je dois pouvoir le trier par le paramètre sij

Quel est le problème avec:

Object [][] data

MODIFIER

Ok, juste deviner que ce dont vous avez besoin est un "StrangeDataStructure" qui contient le tableau et vous aide à trier par la première colonne, alors la seule chose dont vous avez besoin est quelque chose comme ceci:

class Structure {
    Object [][] data;
    Object [] indexColumn; // the sij?
}

Et c'est tout: vous devez ajouter une méthode de tri indiquant la direction, et trier en utilisant le "indexColumn"

C'est VEEERY simple je pense (et si j'ai compris votre "question" )

Tu sais quoi? Je vais la mettre en œuvre.

// le temps s'écoule...

Voici:

import java.util.Comparator;
import java.util.Arrays;

public class StrangeStructure {

    private Integer [][] data;
    private Integer [] sij; // what is sij anyway?

    public StrangeStructure( Integer [][] matrix  ) {
        data = matrix;
        sij = new Integer[ data.length ];
        for( int i = 0 ; i < data.length ; i++ ) {
            sij[i] = data[i][0];
        }
    }

    public void sort( Direction direction  ) {

        Comparator sijComparator  = new DataComparator( direction, true );
        Comparator dataComparator = new DataComparator( direction, false );

        Arrays.sort( sij, sijComparator );
        Arrays.sort( data, dataComparator  );

    }

    public static void main( String [] args ) {

        StrangeStructure s =  
            new StrangeStructure( new Integer[][]{
                                  { 45, 5, 7 }, 
                                  { 33, 1, 6 }, 
                                  { 31, 0, 9 }, 
                                  { 12, 8, 2 }    
                            });

        System.out.printf("Original:\n%s", s );       

        s.sort( Direction.MIN_TO_MAX );  
        System.out.printf("Min to max:\n%s", s );       

        s.sort( Direction.MAX_TO_MIN );  
        System.out.printf("Max to min\n%s", s );       

    }


    public String toString() {
        StringBuilder b = new StringBuilder();
        for( Integer [] row : data ) {
            for( int i : row ) {
                b.append( i+",");
            }
            b.append("\n");
        }
        return b.toString();

    }

}
class DataComparator implements Comparator {

    private Direction direction;
    private boolean isSij;

    public DataComparator( Direction d, boolean isSij ) {
        this.direction = d;
        this.isSij = isSij;
    }

    public int compare( Object one , Object two  ) {
        if( isSij ){
            return doCompare( direction, (Integer) one, (Integer) two );
        } else {
            return doCompare( direction, ((Integer[])one)[0], ((Integer[])two)[0]);
        }
    }
    public int doCompare( Direction d, int one, int two  ) {
        int a = ( d == Direction.MIN_TO_MAX? one: two );
        int b = ( d == Direction.MIN_TO_MAX? two: one ) ;
        return a - b;
    }
    public boolean equals( Object o ) {
        return false;
    }
}



enum Direction{
    MIN_TO_MAX,
    MAX_TO_MIN
}

Sortie:

Original:
45,5,7,
33,1,6,
31,0,9,
12,8,2,
Min to max:
12,8,2,
31,0,9,
33,1,6,
45,5,7,
Max to min
45,5,7,
33,1,6,
31,0,9,
12,8,2,
 15
Author: OscarRyz, 2009-11-07 04:40:24

Lisez la section du tutoriel Swing sur Comment utiliser les tables . Le tutoriel montre comment créer une table ainsi que comment ajouter une capacité de tri à la table.

Si vous avez seulement besoin de stocker les données mais pas de les afficher, vous pouvez utiliser un tableau à 2 dimensions ou une liste de listes. Ensuite, vous pouvez utiliser le comparateur de colonnes pour effectuer le tri.

Edit: ajout de code démontrant l'utilisation du ColumnComparator

import java.util.*;

public class SortSIJ
{
    public static void main(String args[])
    {
        Object[] data = new Object[4];
        data[0] = new Integer[] {45, 5, 7};
        data[1] = new Integer[] {33, 1, 6};
        data[2] = new Integer[] {31, 0, 9};
        data[3] = new Integer[] {12, 8, 2};

        ColumnComparator cc = new ColumnComparator(0);
//      cc.setAscending( false );

        Arrays.sort(data, cc);

        for (Object row: data)
        {
            Integer[] theRow = (Integer[])row;
            System.out.println( Arrays.asList(theRow) );
        }
    }
}

Je suis également d'accord avec la suggestion de créez un objet pour stocker les 3 variables. Dans ce cas, vous pouvez utiliser le BeanComparator qui se trouve sur le lien ci-dessus.

 3
Author: camickr, 2009-11-07 06:11:44

Vous pouvez utiliser le MultiValueMap d'Apache afin de lier plusieurs valeurs avec une clé.

 2
Author: Atmocreations, 2009-11-07 09:06:16

Une option consiste à créer un nouvel objet contenant les 3 variables, puis à créer un tableau/arbre de ces objets et à trier par le paramètre souhaité.

 1
Author: , 2009-11-07 03:34:49

Voici une façon: créer un objet appelé Row pour contenir chaque ligne, puis créer un java.util.HashMap dont les clés sont des sij entiers et dont les valeurs sont les lignes correspondantes.

public class Example
{
  public static class Row
  {
    public Integer sij;
    public Integer i;
    public Integer j;
    public Row(Integer sij, Integer i, Integer j)
    {
      this.sij = sij;
      this.i = i;
      this.j = j;
    }
  }

  public static void main(String[] args)
  {
    Row r1 = new Row(45, 5, 7);
    Row r2 = new Row(33, 1, 6);
    Row r3 = new Row(31, 0, 9);
    Row r4 = new Row(12, 8, 2);
    Map<Integer, Row> map = new TreeMap<Integer, Row>();
    map.put(r1.sij, r1);
    map.put(r2.sij, r2);
    map.put(r3.sij, r3);
    map.put(r4.sij, r4);
    for ( Row row : map.values() ) {
        System.out.println("sij: " + row.sij + " i: " + row.i + " j: " + row.j);
    }
  }
}

Lorsque cela s'exécute, il produit:

sij: 12 i: 8 j: 2
sij: 31 i: 0 j: 9
sij: 33 i: 1 j: 6
sij: 45 i: 5 j: 7
 1
Author: Jim Ferrans, 2009-11-07 04:54:59

Si je comprends bien votre question, tout ce dont vous avez besoin est une classe Comparable pour représenter une ligne.

public static class Row
implements Comparable<Row> {
  public Row(int sij, int i, int j) {
    this.sij = sij;
    this.i = i;
    this.j = j;
  }

  public int compareTo(Row other) {
    return Integer.valueOf(sij).compareTo(other.sij);
  }

  public final int sij;
  public final int i;
  public final int j;
}

Vous pouvez ensuite remplir un List avec des instances de Row et utiliser Collections.sort pour le trier.

 1
Author: finnw, 2009-11-07 12:25:45