Comparator does not sort correctly
I am trying to write a test to highlight the behavior of the following class. This is a comparator for a website, but for some reason the "propertiesCreatedBy" section is not working. This is a very strange problem as long as the rest of the fields work and can be sorted correctly, but when trying to sort on this column, the order seems random:
import java.io.Serializable;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
public class CaseNoteDTOComparator implements Comparator, Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
protected class CaseNoteDTOComparatorInternal implements Serializable {
private String[] properties = null;
boolean[] shouldReverse = null;
public CaseNoteDTOComparatorInternal(String[] properties, boolean[] shouldReverse) {
this.properties = properties;
this.shouldReverse = shouldReverse;
}
public int compare(Object obj1, Object obj2) {
int result = 0;
for (int i = 0; i < properties.length; i++) {
JavaBeanNamedPropertyComparator comparator =
new JavaBeanNamedPropertyComparator(properties[i], shouldReverse[i]);
result = comparator.compare(obj1, obj2);
if(result != ComparatorConstants.EQUAL) {
return result;
}
}
//actually object are equals....
return ComparatorConstants.LESS_THAN;
}
public void setDescending(boolean descending) {
for (int i = 0; i < shouldReverse.length; i++) {
shouldReverse[i] = descending;
}
}
}
private static Map comparators = new HashMap();
//statically initialise comparators
{
final String[] propertiesEffectiveDate = { EFFECTIVE_DATE_NAME, CREATED_ON };
boolean[] shouldReverseEffectiveDate= {false, false};
comparators.put(EFFECTIVE_DATE_NAME, new CaseNoteDTOComparatorInternal(propertiesEffectiveDate, shouldReverseEffectiveDate));
final String[] propertiesId = { ID_NAME };
boolean[] shouldReverseId = {false};
comparators.put(ID_NAME, new CaseNoteDTOComparatorInternal( propertiesId, shouldReverseId));
final String[] propertiesType = { TYPE_NAME, ID_NAME };
boolean[] shouldReverseType = {false, false};
comparators.put(TYPE_NAME, new CaseNoteDTOComparatorInternal( propertiesType, shouldReverseType));
final String[] propertiesTitle = { TITLE_NAME, ID_NAME };
boolean[] shouldReverseTitle = {false, false};
comparators.put(TITLE_NAME, new CaseNoteDTOComparatorInternal( propertiesTitle, shouldReverseTitle));
final String[] propertiesRecordedVS = { PERSON_LASTNAME_NAME, PERSON_FIRSTNAME_NAME, ID_NAME };
boolean[] shouldReverseRecordedVS= {false, false, false};
comparators.put(RECORDED_VS, new CaseNoteDTOComparatorInternal( propertiesRecordedVS, shouldReverseRecordedVS));
final String[] propertiesCreatedBy = { CREATED_BY_LASTNAME_NAME, CREATED_BY_FIRSTNAME_NAME, ID_NAME };
boolean[] shouldReverseCreatedBy= {false, false, false};
comparators.put(CREATED_BY_NAME, new CaseNoteDTOComparatorInternal( propertiesCreatedBy, shouldReverseCreatedBy));
final String[] propertiesOrganisation = { ORGANISATION_NAME, ID_NAME };
boolean[] shouldReverseOrganisation= {false, false};
comparators.put(ORGANISATION_NAME, new CaseNoteDTOComparatorInternal( propertiesOrganisation, shouldReverseOrganisation));
final String[] propertiesScore = { LUCENE_INDEX_SCORE};
boolean[] shouldReverseScore = {false};
comparators.put(LUCENE_INDEX_SCORE, new CaseNoteDTOComparatorInternal( propertiesScore, shouldReverseScore));
}
private CaseNoteDTOComparatorInternal comparator = null;
public static final String ID_NAME = "id";
public static final String EFFECTIVE_DATE_NAME = "effectiveDate";
public static final String TYPE_NAME = "displayCaseNoteType";
public static final String TITLE_NAME = "title";
public static final String PERSON_LASTNAME_NAME = "personLastName";
public static final String PERSON_FIRSTNAME_NAME = "personFirstName";
public static final String RECORDED_VS = "recordedVS";
public static final String CREATED_BY_NAME = "createdBy";
public static final String CREATED_BY_FIRSTNAME_NAME = "createdByFirstName";
public static final String CREATED_BY_LASTNAME_NAME = "createdByLastName";
public static final String CREATED_ON = "createdOn";
public static final String ORGANISATION_NAME = "organisationName";
public static final String DEFAULT_FIELD_NAME = EFFECTIVE_DATE_NAME;
public static final String LUCENE_INDEX_SCORE = "score";
public CaseNoteDTOComparator(String fieldKeyName, boolean descending) {
this.comparator = (CaseNoteDTOComparatorInternal)comparators.get(fieldKeyName);
if(comparator==null) {
this.comparator = (CaseNoteDTOComparatorInternal)comparators.get(DEFAULT_FIELD_NAME);
}
comparator.setDescending(descending);
}
public int compare(Object obj1, Object obj2) {
return comparator.compare(obj1, obj2);
}
}
I've spent several hours looking at the code and experimenting, but can't find what's wrong. More than a test implementation for a class, I'd like to fix it, but can't seem to find the problem. I would really appreciate any hint.
Thank!
source to share
My guess is this is a data problem. You are returning ComparatorConstants.LESS_THAN
on equal values โโ(why?), Which means that the equivalent data will be randomly ordered.
Returning less than equal values โโalso leads to infinite loops if the sorting algorithm cannot tolerate this case.
Are you sure these fields are filled in correctly and you mean them by the correct name?
source to share