Sverd
Sverd

Reputation: 331

Table like java data structure

I need to implement some kind table-like data structure that stores info like this in Java:

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

and I have to be able to sort the table by the sij parameter. I've made some tests with ArrayList and HashMap, but I can't make them work well.

Upvotes: 31

Views: 95369

Answers (7)

Andrejs
Andrejs

Reputation: 27687

There is a generic TreeBasedTable class from Google library which does exactly what you are asking for. It also offers many other useful utility methods and its usage is shown in the user guide.

From the TreeBasedTable docs:

Implementation of Table whose row keys and column keys are ordered by their natural ordering or by supplied comparators.

Example usage:

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]

Upvotes: 27

finnw
finnw

Reputation: 48629

If I understand your question right, all you need is a Comparable class to represent a row.

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

You can then populate a List with instances of Row and use Collections.sort to sort it.

Upvotes: 2

Atmocreations
Atmocreations

Reputation: 10061

You could use the MultiValueMap from Apache in order to link multiple values with one key.

Upvotes: 2

camickr
camickr

Reputation: 324118

Read the section from the Swing tutorial on How to Use Tables. The tutorial shows how to create a table as well as how to add sorting capability to the table.

If you only need to store the data but not display it, then you can use a 2-dimensional array or a List of Lists. Then you can use the Column Comparator to do the sorting.

Edit: added code demonstrating use of the 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) );
        }
    }
}

I also agree with the suggestion to create an Object to store the 3 variables. In this case you can use the BeanComparator which can be found at the above link.

Upvotes: 4

Jim Ferrans
Jim Ferrans

Reputation: 31012

Here's one way: make an object called Row to hold each row, and then make a java.util.HashMap whose keys are Integer sij's and whose values are the corresponding Rows.

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

When this runs it produces:

sij: 12 i: 8 j: 2
sij: 31 i: 0 j: 9
sij: 33 i: 1 j: 6
sij: 45 i: 5 j: 7

Upvotes: 2

OscarRyz
OscarRyz

Reputation: 199224

What do you mean with:

i have to be able to sort it by the sij parameter

What's wrong with:

Object [][] data

EDIT

Ok, just guessing that what you need is a "StrangeDataStructure" which holds the array, and helps you to sort by the first column, then the only thing that you need is something like this:

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

And that's it: you should add a sort method indicating the direction, and sort using the "indexColumn"

It is VEEERY simple I think ( and If I understood your "question" )

You know what? I'm going to implement it.

// time elapses...

Here it is:

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
}

Output:

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,

Upvotes: 21

user181494
user181494

Reputation:

One option is to create a new object that contains the 3 variables, and then make an array/tree of those objects, and sort by the parameter you want.

Upvotes: 1

Related Questions