31

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.

7
  • Do you mean you have to sort the rows by the values in the first column? Commented Nov 7, 2009 at 2:01
  • exactly! by the sij parameter Commented Nov 7, 2009 at 2:57
  • @Bill the Lizard: What is he talking about? Commented Nov 7, 2009 at 3:38
  • No partial code, no specific question, just "hope you can help me!"? How exactly do you want us to help you? Commented Nov 7, 2009 at 4:50
  • I've clarified the language a bit, hopefully without distorting it. Commented Nov 7, 2009 at 5:01

7 Answers 7

27

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]
Sign up to request clarification or add additional context in comments.

Comments

22

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,

2 Comments

hi, thanks for answer. the sij parameter is a value derived from i and j , like a distance between them. using an array matrix, i will loose the reference. imagine i need to sort by "sij" from min to max : i want to get : 12 8 2 31 0 9 etc
I still don't get it. It may be obvious to you because you've been working on that, but not for me. I'm sure if you explain further with examples what is that sij all about, you'll get better answers. Click on edit in your original post and explain that. Using examples always work.
4

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.

Comments

3

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.

2 Comments

But what if I want a table that is generic?
not sure why you're getting downvoted for this, its basically the textbook solution.
2

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

Comments

2

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

1 Comment

Unfortunately MultiValueMap is not sorted.
1

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.

2 Comments

great idea. how could i then sort in array?
Google Quicksort or Mergesort

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.