|
The Comparer
Last post 11-17-2012 12:55 AM by Ben L.. 22 replies.
-
11-06-2012 1:00 PM
|
|
-
zelmak


- Joined on 07-14-2010
- Posts 422
|
Most of the Swing GUI code in the user-side of our Java application predates Java 1.4. In Java (1.)6, JTables (think DataGrid or the like) got a makeover providing in-built sorting and filtering capabilities; pre-(1.)6 coders had to work around this by creating TableModels which would providing sorting and/or filtering. Our coders did the same, albeit poorly IMO. They created Sorter (not SortingTableModel or TableSorter ... just Sorter) which extends AbstractTableModel (good) and wraps a provided TableModel (also good).
But the rest of it is quite something to behold.
Apparently, they were having synchronization trouble with the underlying TableModel -- it would get updated by the owning data source provider on a separate thread and not fire any events notifying listeners that the model had been changed. So they (tried to) deal with it thusly: private void checkTable() {
// see if the model was updated
//fix for exception caused by unsynchronized threads
for (int x = 0; x < 20000 && this.index.length != this.model.getRowCount(); x++) {
}
if (this.index.length != this.model.getRowCount() {
throw new RuntimeEXception("sorter not informed of a change in the model: "
+ this.index.length
+ " rows in index, "
+ this.model.getRowCount()
+ " rows in table");
}
}
So they traded one exception for another. Super. And in modern JVMs, the whole loop is likely to be optimized out.
:sigh:
But my favorite, is this snippet of a method to compare two rows by a given column: private TableModel model = ....
.
.
.
private int compareRowsByColumn(int row1, int row2, int column) {
Object o1;
Object o2;
int result;
// compare the rows
o1 = model.getValueAt(row1, column);
o2 = model.getValueAt(row2, column);
if (( o1 == null) && (o2 == null)) {
result = 0;
} else if (o1 == null) {
result = -1;
} else if (o2 == null) {
result = 1;
} else
// neither were null
if (o1 instance of java.lang.Number) {
double d1 = (( Number )o1).doubleValue();
double d2 = (( Number )o2).doubleValue();
if (d1 == d2) {
result = 0;
} else if (d2 < d1) {
result = 1;
} else {
result = -1;
}
} else if (o1 instanceof java.lang.Date) {
Date d1 = (Date) o1;
Date d2 = (Date) o2;
result = d1.compareTo(d2);
} else if (o1 instanceof java.lang.Boolean) {
boolean b1 = ((Boolean)o1).booleanValue();
boolean b2 = ((Boolean)o2).booleanValue();
if (b1 == b2) {
result = 0;
} else if (b1) {
result = 1;
} else {
result = -1;
}
} else if (o1 instanceof ComparableType1) {
ComparableType1 ct1 = (ComparableType1) o1;
ComparableType1 ct2 = (ComparableType1) o2;
result = ct1.compareTo(ct2);
} else if (o1 instanceof (ComparableType2) {
ComparableType2 ct1 = (ComparableType2) o1;
ComparableType2 ct2 = (ComparableType2) o2;
result = ct1.compareTo(ct2);
} else {
.
. total of 12 ComparableTypes ...
.
} else {
String s1 = o1.toString();
String s2 = o2.toString();
result = s1.compareTo(s2);
}
return result;
}
Instead of using polymorphism they created this monster (which was added to over the years as various things needed to be displayed in a Sorter-backed JTable. Well, being the clever guy I thought I was, I decided to add the polymorphism bit: ...
// neither were null
if ( o1 instanceof Comparable ) {
Comparable c1 = (Comparable) o1;
Comparable c2 = (Comparable) o2;
result = c1.compareTo(c2);
} else
...
I tested it with data, it worked, sorted properly and all was hunky dory.
Until it went into operations.
As it turns out, someone thought it would be clever to handle the cases where there was no data (apparently null cells are to be avoided at all costs!) and create their own comparable object to stuff into a model cell when the actual value was null so the user would have something nice to look at: public class EmptyElement implements
Comparable {
public String toString() {
return "N/A";
}
public boolean equals(Object o) {
try {
if (this.compareTo(o) == 0) {
return true;
}
} catch (Exception e) {
}
return false;
}
public int compareTo(Object o) throws ClassCastException {
if (( o != null ) && ( o instanceof EmptyElement )) {
return 0;
} else {
return 1;
}
}
}
As you no doubt can guess, this breaks sorting ... some values will be compared by Number, or Date or something that makes sense ... but when a comparison is made against a cell containing EmptyElement, it drops into string-compare mode ... thus, N/A's will be ordered in the list somewhere south of 'middle', on average. This confuses users.
But worse, it breaks my polymorphic check since it assumes (hah!) that columns are homogenous types ... nulls are caught ahead of my insertion. My new call would create a ClassCastException when stumbling upon an EmptyElement.
It was easiest just to take out my code.
|
|
-
-
snoofle


- Joined on 06-22-2006
- Posts 1,444
|
zelmak:It was easiest just to take out my code.
Been there, feel your pain. Or, you could always try something evil, like: result = c1.toString().compareTo(c2.toString());
|
|
-
-
-
zelmak


- Joined on 07-14-2010
- Posts 422
|
snoofle:
zelmak:It was easiest just to take out my code.
Been there, feel your pain.
Or, you could always try something evil, like: result = c1.toString().compareTo(c2.toString());
Is that not essentially the last branch of the huge if-else-if-else? I'm trying to see something tricksy there ... if there's something tricky about your suggestion, I'm not seeing it ... then again ... I've spent the day trying to untangle Sorter and use "JTable 6" instead ... I don't think its possible without a major re-write.
|
|
-
-
-
Cassidy


- Joined on 01-09-2012
- Posts 2,839
|
zelmak: Java 1.4. In Java (1.)6 <obligatory derail> Just had a thought... what happens after Java 1.7 becomes 1.8 then 1.9...? "No, I know Java 1.4 *is* Java2, but it's not Java 2.0, that came after Java 9... look - fuck it, we need to upgrade, okay?"
|
|
-
-
fatbull


- Joined on 10-06-2008
- [5;31;43m
- Posts 215
|
zelmak:As it turns out, someone thought it would be clever to handle the cases where there was no data (apparently null cells are to be avoided at all costs!) and create their own comparable object to stuff into a model cell when the actual value was null so the user would have something nice to look at:
Consider using a custom TableCellRenderer instead.
CLI is like a text adventure.
|
|
-
-
Severity One


- Joined on 12-04-2008
- Malta
- Posts 363
|
Cassidy:Just had a thought... what happens after Java 1.7 becomes 1.8 then 1.9...? "No, I know Java 1.4 *is* Java2, but it's not Java 2.0, that came after Java 9... look - fuck it, we need to upgrade, okay?"
Java 11g.
|
|
-
-
ubersoldat


- Joined on 04-03-2008
- Posts 219
|
Severity One: Cassidy:Just had a thought... what happens after Java 1.7 becomes 1.8 then 1.9...? "No, I know Java 1.4 *is* Java2, but it's not Java 2.0, that came after Java 9... look - fuck it, we need to upgrade, okay?"
Java 11g.
+1... sadly :-(
Oh! And nice way of fucking up the whole Comparable idea provided by Java.
|
|
-
-
curtmack


- Joined on 10-25-2007
- Posts 148
|
ubersoldat: Severity One: Cassidy:Just had a thought... what happens after Java 1.7 becomes 1.8 then 1.9...? "No, I know Java 1.4 *is* Java2, but it's not Java 2.0, that came after Java 9... look - fuck it, we need to upgrade, okay?"
Java 11g.
+1... sadly :-(
Oh! And nice way of fucking up the whole Comparable idea provided by Java. On a related note, one of the improvements slated for Java 8 is the ability to use lambda expressions for, among other things, Comparators. (More generally, you'll be able to use a lambda expression anywhere you could use an object instance of any interface that provides a single method - Comparator, ActionListener, Runnable, and others, as well as user interfaces meeting that requirement. The compiler will detect from context which interface type that lambda fills (taking polymorphism into account), and then magically wrap it up into an object implementing that interface providing the lambda as that single method.)
|
|
-
-
zelmak


- Joined on 07-14-2010
- Posts 422
|
fatbull:
zelmak:As it turns out, someone thought it would be clever to handle the cases where there was no data (apparently null cells are to be avoided at all costs!) and create their own comparable object to stuff into a model cell when the actual value was null so the user would have something nice to look at:
Consider using a custom TableCellRenderer instead.
You know that. I know that. Hell, we all know that (or should.) However, the original coders were C/C++ coders who were learning Java while building this system from the ground up under contract. So they made it work.
|
|
-
-
zelmak


- Joined on 07-14-2010
- Posts 422
|
curtmack:On a related note, one of the improvements slated for Java 8 is the ability to use lambda expressions for, among other things, Comparators.
(More generally, you'll be able to use a lambda expression anywhere you could use an object instance of any interface that provides a single method - Comparator, ActionListener, Runnable, and others, as well as user interfaces meeting that requirement. The compiler will detect from context which interface type that lambda fills (taking polymorphism into account), and then magically wrap it up into an object implementing that interface providing the lambda as that single method.)
Portions of our code have broken when going from Java (1.)6 u13 to Java (1.)6 u17 (latest (1.)6 is u33, I believe) -- we fixed what was obviously broken (i.e., not working at all) ... we haven't tried Java (1.)7 yet.
Upgrades to infrastructure frighten me.
|
|
-
-
Severity One


- Joined on 12-04-2008
- Malta
- Posts 363
|
curtmack:On a related note, one of the improvements slated for Java 8 is the ability to use lambda expressions for, among other things, Comparators.
Well, let's wait and see. We waited 4.5 years for Java 7, and wen it finally arrived the new features were not exactly earth-shattering. Try-with-resource is nice, although I expect that opening database connections, statements and result sets still remains a mess. Catching of multiple exceptions is nice too, and there's been an overhaul in some APIs. Other than that, though...
|
|
-
-
-
-
Adanine


- Joined on 10-16-2012
- Posts 105
|
Cassidy: zelmak: Java 1.4. In Java (1.)6 <obligatory derail> Just had a thought... what happens after Java 1.7 becomes 1.8 then 1.9...? "No, I know Java 1.4 *is* Java2, but it's not Java 2.0, that came after Java 9... look - fuck it, we need to upgrade, okay?"
I've always through a version "number" was technically two, the first being a major release and the second number being a minor update (The third being a bug fix, the forth being a build no, in some cases I've seen). So it'll go to Java 1.11. Just to confuse things more. Pretty sure Cassidy knew that (I'm one of those people that judges intellect by # of posts), but maybe someone didn't...
|
|
-
-
Cassidy


- Joined on 01-09-2012
- Posts 2,839
|
Adanine:I'm one of those people that judges intellect by # of posts Two words. The first is "Spectate". You may guess the second.
|
|
-
-
Ben L.


- Joined on 12-22-2010
- HELP I'M TRAPPED IN A COMMUNITY SERVER FACTORY
- Posts 1,875
|
Cassidy: Adanine:I'm one of those people that judges intellect by # of posts Two words. The first is "Spectate". You may guess the second.
If post count gives intellect, swampy should have rolled a mage.
|
|
-
-
boomzilla


- Joined on 12-11-2007
- NOVA
- Posts 3,987
|
Ben L.:If post count gives intellect, swampy should have rolled a mage.
What makes you think he didn't? Ask him about his rocks some time.
早安,我抱歉有沒有在這封電子郵件中的商業秘密或加拿大色情。請停止殺害酷動物啄木鳥醫學。剛剛買了一些偉哥了
|
|
-
-
Sutherlands


- Joined on 07-24-2008
- Posts 1,434
|
boomzilla: Ben L.:If post count gives intellect, swampy should have rolled a mage.
What makes you think he didn't? Ask him about his Ioun stones some time.
NTUFY
|
|
-
-
curtmack


- Joined on 10-25-2007
- Posts 148
|
Sutherlands: boomzilla: Ben L.:If post count gives intellect, swampy should have rolled a mage.
What makes you think he didn't? Ask him about his Ioun stones some time.
NTUFY
Ioun stones.
|
|
-
-
Sutherlands


- Joined on 07-24-2008
- Posts 1,434
|
curtmack: Sutherlands: boomzilla: Ben L.:If post count gives intellect, swampy should have rolled a mage.
What makes you think he didn't? Ask him about his Ioun stones some time.
NTUFY
Ioun stones.
403 Forbidden error.
|
|
-
-
Ben L.


- Joined on 12-22-2010
- HELP I'M TRAPPED IN A COMMUNITY SERVER FACTORY
- Posts 1,875
|
Sutherlands: curtmack: Sutherlands: boomzilla: Ben L.:If post count gives intellect, swampy should have rolled a mage.
What makes you think he didn't? Ask him about his Ioun stones some time.
NTUFY
Ioun stones.
403 Forbidden error.
|
|
Page 1 of 1 (23 items)
|
|
|