This week's book giveaway is in the General Computing forum. We're giving away four copies of Arduino in Action and have Martin Evans, Joshua Noble, and Jordan Hochenbaum on-line! See this thread for details.
The last time I was asked to write sort-break logic was about 15 years ago in cobol. Since that time, it's been handled very elegantly for me in SQL, via clauses such as "GROUP BY".
For my current java project, a database is not at my disposal, so I have to do it "the old fashioned way", with classic "sort-break" logic. I'm not sure it even goes by the same name these days, but here's my question:
Anyone know of a good pattern for sort-break logic in java, with perhaps an example?
Something that uses the Comparator that I just mentioned in a another javaranch thread, would be nice.
I can design and code it all myself, but I don't feel like re-inventing this particular wheel that's probably been done a million times by now.
Originally posted by Ben Ethridge: Something that uses the Comparator that I just mentioned in a another javaranch thread, would be nice.
Isn't sort-break logic more for grouping so you can get subtotals and such? I don't think a Comparator would be appropropriate to use to implement sort-break logic. I could be missing something but I don't even see how a Comparator can be used to do that and still be just a Comparator. I could see you writing a SortBreak class that monitors for a change in a value by using a a Comparator. The Observer Pattern might be something you could use.
Hmmm, I'd likely fall back on my old COBOL days. Say I got a result set of sales info sorted by region, state, store.
Each start routine is a chance to initialize counters and totals and such. Each end routine is a chance to report counts and totals or roll them up to the next level. If you make each nested level a new method it won't creep off the right side of the screen so bad.
This is a case of what PJ Plauger called "the program looks like the output". Pleasing in its own way.
Any other less blatantly procedural ideas?
A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
Ben Ethridge
Ranch Hand
Joined: Jul 28, 2003
Posts: 108
posted
0
I think I get the jist of what you're saying (or remembering from way back :-), in that you are trying to code for multiple sort breaks, i.e. multiple "GROUP BY" levels, in SQL terms, but I don't quite see where you are advancing the rows and where you're not. Looks to me that you have two advance-the-row points?
I remember that the devil was in the details of the ordering of the retrieving the next row, the accumulation and the write-and-zero'ing of the totals. I've run this through every file/record pattern I can think of, on paper, so I think this will work for me, unless someone sees a flaw in it. Here it is in pseudo-java:
If (fileNotEmpty) { Read the first rec into currentRec; //"priming read", we used to call it. While (readNextRec){ accumulate currentRec to totals; if (currentRec.sortKey != nextRec.sortKey) { write and zero the totals; } currentRec = nextRec; }
Possible states at this point: ( ) EOF and only first rec read. ( ) EOF and last rec = prev rec. ( ) EOF and last rec != prev rec. Because of the logic sequence above, the final rec is handled by:
accumulate currentRec to totals; write and zero the totals; }
Sort Key Record amount Total A 1.00 1.00 (written) B 2.00 2.00 B 5.00 7.00 (written) ----------------------------------------------------------- A 1.00 1.00 (written) B 2.00 2.00 (written) C 5.00 5.00 (written) ----------------------------------------------------------- A 1.00 1.00 A 2.00 3.00 (written) B 5.00 5.00 (written) ----------------------------------------------------------- A 1.00 1.00 A 2.00 3.00 A 5.00 8.00 (written)
Stan James
(instanceof Sidekick)
Ranch Hand
Joined: Jan 29, 2003
Posts: 8791
posted
0
What you sketched out is very much like a single level of what I sketched out. one big difference is that I get next (read or advance) at the innermost or lowest level. Try getting the count & total of sales with pencil & paper on data like:
eastern PA Scranton $1 eastern PA Allentown $4 eastern PA Allentown $2 eastern NJ Hoboken $5 eastern NJ Bridgewater $10 central NE Lincoln $6 central NE Lincoln $8 central NE Lincoln $3 central KS Wichita %7 central KS Topeka $9
I had no startReport() by accident. You want that to initialize your grand totals to 0. And I didn't mention EOF handling. You'd have to make sure that EOF makes each loop terminate. I might the loops as while(not EOF and current == prior).
I'd also break out methods to reduce the right creep:
With the methods separated, you might see that you could make an object for each level - State, Store and Region. They would have a public method to doOneWhatever, and private start and stop methods. The object state would be the accumulation for that level. Could be interesting.
If I had to do two or more reports against the same data I'd put this looping logic in one class and all the start* end* and the lowest level doSalesRecord methods in a custom reporting class. Lemme know if that made any sense.
That's a nice example of the use of Comparator with Collections.sort, but what we need now is the "break" functionality of the old "sort-break" algorithm.
I've had a tough time finding a pattern in java code for this anywhere on the internet, so I wrote my own, as I showed above. I first learned this sort-break algorithm in a cobol class, back in the early 80's. It was such a common pattern back then, but with the coming of relational databases and the SQL GROUP BY clause, I'm thinking that everyone (including me :-) has been delegating the sort-break logic to the database, i.e. no one is using flat-file-style sort-break logic anymore...
...But then, the part of the puzzle that still seems missing, is that we DO have the "sort" piece of the sort-break pattern pretty well laid out and javadoc'd, via Comparator and Collections.sort (ORDER BY functionality in SQL), so surely there must also be a need for the "break" piece of the pattern (i.e. the GROUP BY functionality in SQL).
Ben
Stan James
(instanceof Sidekick)
Ranch Hand
Joined: Jan 29, 2003
Posts: 8791
posted
0
I have a generic object that works with any result set. Working from the first column to the last if the value equals the prior row it prints an equal sign, otherwise it prints values from that column on. The output looks like this:
Let's say this generic thing knew what columns were breaks and called a custom reporter for each break.
and the break handler interface was something like: