• Post Reply Bookmark Topic Watch Topic
  • New Topic

sort-break pattern in java?  RSS feed

 
Ben Ethridge
Ranch Hand
Posts: 108
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi, all.

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.

Ben Ethridge
Integration Consultant, SCJP 1.4
 
Junilu Lacar
Sheriff
Posts: 11494
180
Android Debian Eclipse IDE IntelliJ IDE Java Linux Mac Spring Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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?
 
Ben Ethridge
Ranch Hand
Posts: 108
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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;
}

Example file/record patterns I used:

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
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
Max Rahder
Ranch Hand
Posts: 177
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This example might provide food for thought:
 
Ben Ethridge
Ranch Hand
Posts: 108
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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:

Any of that sound like fun?
 
Ben Ethridge
Ranch Hand
Posts: 108
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, that looks interesting.

Ben
 
Gary Down
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Is this of any use??
Reporter

Just an old cobol programmers sugestion to another...

Gary,
 
Stan James
(instanceof Sidekick)
Ranch Hand
Posts: 8791
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Cool. I like the use of comparators and filters.
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!