Reputation: 975
I have a table full of values where the first 2 digits are a year the next 3 digits are a value between 0 and 999 and the final 2 characters are 2 alphaOnly characters. A few example values: 0, 0, 99001AG, 99002FG, 54001AG, 54050AB, There are also a few instances where the value is just a 6 digit String SGP4DC. There will be multiple of values that are SGP4DC. The 0's are bad data but I have to account for them for the testing purposes.
Special cases: Because of the two digit year, when sorting descending, launches from 1999 (e.g. 99001A) are always sorted as "greater" than launches from the 2000's (e.g. 06001A). The special handler should ensure that any items between 00 and 56 are sorted as greater than any items between 57 and 99.
Now my sorting goal is to first order by the first 2 digits to take care of the above special case. Then follow that up with the following 3 digits. And finally just a string sort on the last 2 characters. And finally follow that up with the String compare of values that dont start with 2 numerical digits.
Example of expected sorted in ascending order would be 0 0 60001AG 60002FB 42001AG 42002GD APG4GP APG4GP
Again note if the 2 leading digits are greater than or equal to 57 it represents 1957-1999. And if the 2 leading digits are less than 57 they represent 2000-2056.
Finally my code. Note I have some bogus data currently in the table with values for 0. Thus I was attempting to make them less than everything else. I do not have the power to remove the 0's so i'm trying to code around them. IE 0's will always show up after the above sorted list.
@Override
public int compare(String o1, String o2) {
if(o1.equals("0") && o2.equals("0")){
return 0;
}
System.out.println("Comparing " + o1 + " and " + o2);
if (o1.length() == 1) {
return -1;
}
if (o2.length() == 1) {
return 1;
}
String o1year = null;
String o2year = null;
Integer obj1year;
Integer obj2year;
if (o1.length() >= 2) {
o1year = o1.substring(0, 2);
}
if (o2.length() >= 2) {
o2year = o2.substring(0, 2);
}
if (isInteger(o1year)) {
if (isInteger(o2year)) {
obj1year = Integer.parseInt(o1year);
obj2year = Integer.parseInt(o2year);
// handles years 2000 - 2056 being greater than anything from
// ##57-##99
if (obj1year < 57 && obj2year > 56) {
return 1;
}
if (obj1year == obj2year) {
int returnValue = compareIncriment(o1, o2);
if(returnValue == 0){
return o1.compareToIgnoreCase(o2);
}
return returnValue;
}
if (obj1year > obj2year) {
return 1;
} else {
return -1;
}
}
return 1;
}
// object 2 starts with a 2 digit year and object 1 didnt
if (isInteger(o2year)) {
return -1;
}
// final return
return o1.compareToIgnoreCase(o2);
}
private int compareIncriment(String o1, String o2) {
// TODO Auto-generated method stub
int inc1;
int inc2;
if(isInteger(o1.substring(2, 4))){
inc1 = Integer.parseInt(o1.substring(2, 4));
}else if(isInteger(o1.substring(2, 3))){
inc1 = Integer.parseInt(o1.substring(2, 3));
}else{
inc1 = Integer.parseInt(o1.substring(2, 2));
}
if(isInteger(o2.substring(2, 4))){
inc2 = Integer.parseInt(o2.substring(2, 4));
}else if(isInteger(o2.substring(2, 3))){
inc2 = Integer.parseInt(o2.substring(2, 3));
}else{
inc2 = Integer.parseInt(o2.substring(2, 2));
}
return inc1 - inc2;
}
Updated Code***
I currently see nothing in my table and i'm getting a Comparison method violates its general contract error.
Upvotes: 0
Views: 168
Reputation: 72044
You should write unit tests for your comparator to discover bugs. You should also factor your code better, because your function is very hard to understand. First, classify the product code into the "0" case, the year-included case, and the no-year case. If the two codes are not in the same class, return the appropriate result.
If they are in the same class, factor out the specific comparisons into separate functions, or even separate Comparators. Having separate Comparators makes them easier to test; separate functions would be harder to justify making public.
I found one bug by looking at the code: for c.compare("0", "0")
it returns -1
when it should return 0
. Beyond that, it's really hard to tell.
Upvotes: 1