I have a table in which I am keeping track of a large set of subsets of the rows. My problem is that users are allowed to add and subtract rows from the table. So if I have a list of rows: 1,2,3 I am in good shape until row 2 is deleted. Long ago in another language, I could handle that easily because the table maintained an internal row id and an external row id. So I just defined my sets in terms of the internal id and used a function that returned the external id. I've been looking for something like that in Java. I found functions related to sorting the table, but so far nothing that would help with adding and deleting rows.
this won't compile of course, as I haven't found functions that map an absolute address to a relative one.
Is there anything like this in Java?
I can loop through all my clusters and update every reference each time a row is added or deleted, but I was hoping for something cleaner than that.
underneatht the table is a tablemodel that contains the data, so in there is all the data you have. so you have 2 options
1, get the model from the table and low and behold all the data from the table, but not in a way you would like it or
2, make your own table model (extending DefaultTableModel if I remember correctly).
Wendy is correct. We usually discuss JTables elsewhere, so I shall move this thread.
Joined: Oct 10, 2011
Stefaan, thanks for the comment about LinkedList. That is a more efficient way to handle my sets.
However, for the sets to be useful, they need to contain invariant row ids. Which gets back to my original question of whether there is a way to return invariant row ids from the default table model. I'm going to assume that there isn't, or someone would have posted the method call. I'm spoiled always having had that functionality in table packages I have used in other languages.
I don't change columns, but if I were to switch to invariant row ids, it would seem that I would need to override:
1. The constructor, so that I could initialize my invariant ids.
then add my own methods to translate the invariant row ids. Though, if I was implementing this with an array for which I never actually removed rows, but simply marked them as deleted, it would seem like I might need to override the column methods as well, as the default methods wouldn't know what to do with that structure.
It sounds simpler to maintain the mapping external to the table.
the point is if you make your own table model, the rows will be removed from your linked list by the table calls (remove row) which provides a rownum.
I would personally use an array list so you can index it using the values passed into the methods.
Joined: Oct 13, 2005
Agree. Linked Lists give slower performance for finding contents than array lists.
Joined: Oct 10, 2011
Wendy, thanks for responding. I think I need a little more explanation to understand your suggestion.
Here is my situation. I need to run calculations on specific rows in my table. Each calculation has a list of the rows it should use. When I add a row, I need to to figure out which calculation to do and then add the row to the appropriate list. I have a listener that responds when a row is added (or deleted).
Now, let's say the first list contains rows 1,3,4 and the second list rows 2,5,6. The user deletes row 2. My goal is to remove row 2 from the list and rerun the calculation on what were rows 5 and 6. Except they aren't anymore. They are now rows 4 and 5. Likewise the first list should now read 1,2,3. I have this problem whenever I delete a row or add a row anywhere except the end of the table.
brute-force #1: typically there will be 100 or so lists, loop over them all and update the row ids. This can be done by my listeners for add and remove rows.
brute force #2: when a row is added or removed, redo all the calculations that assign the rows to a specific list. This means looping over all the rows in the table. Because calculations are involved, this might be slower that #1.
invariant ids: here I would store a,c,d and b,e,f. Then if row 2 was deleted, I would call a function that would say 2 maps to b and remove b. The inverse would be to call a function that said what e, for example, was currently mapped to. Before deletion, it would map to 5, after deletion it would map to 4. So I would not need to modify my lists, my methods would be passed the invariant list and do the conversion using the appropriate function.
If I want invariant ids, I could create an object which is my mapping and call methods on it when I add a row, delete a row or need to convert from invariant to table row id or vice versa. I would call the method when I add and remove rows.
Or (in theory, as I am a bit sketchy on extending a table model for anything other than setting specific columns to be editable and things like that) I could use a table model that inherently supports the concept of invariant ids. One way I have seen this done is by adding an additional column to the underlying structure. That column contains the displayed row id or -1 if the row was deleted. The invariant id is the row number of this structure (new rows are always added at the end, rows are never deleted). That would seem to require that I override the constructor so that I can set up this array, and since it needs to return or set values based on the first column and will never actually remove a row, override all the methods that do anything with rows and columns.
I also know that if rows are sorted, there are functions to convert back and forth between the original row order and the sorted order (convertRowIndexToView and convertRowIndexToModel) and I was hoping the solution to my problem was as simple as getting equivalent methods for invariant ids.
I was thinking about this whilst my baby kept me awake last nigh (3am)
How you organise your data depends on what you are going to be doing most, if it is running the calculations, the id needs to be the key of your data structure. whereas if looking at the data through the jtable is the most common action, the table row index needs to be the key.
My solution above implements the jtable being the main user of the data.