Search code examples
javaalgorithmsortingcomparatoricomparable

Custom Comparator to sort list of states, counties and zip codes


I'm having hard time to write comparator to sort list of custom objects with the following string fields: 1. Branch Class --> Can be state, county or zip code and used to identify which data field is it; can't be empty 2. State --> State Name, can't be empty 3. Geography --> If branch class.equals'county', it will hold the county name, can be empty 4. zip --> zip code. Can be empty for states and counties 5. ParentNodeId --> the name of the parent that should be applicable for this tree. For example, a state has no parent (empty string) while the county has the state as parentNodeId and the zipCode has the county as the parentNodeId. So, for geography object with branch = "state", zipCode "36003", the parentNodeId should be Autauga and state is "AL". For geography object with branch ="county" and geography = "Autauga", then the parentNodeId is "AL".

The current object list is in the form: state - state - state - county - county - zip code - zip code

While I'm looking to have a list of

-state

-- County

-- Zip Code

-- Zip Code

-- County

-- Zip Code

-State

-- County

and so on.

My trial is still missing cases that I'm not aware of. Here's my code

public static final Comparator<Geography> BY_STATE_COUNTY_ZIP_COMPARATOR = new Comparator<Geography>() {

public int compare(final Geography obj1, final Geography obj2) {

    if (obj1.getZip().equals("89420") || obj2.getZip().equals("89420") || obj1.getGeography().equals("Mono")
            || obj2.getGeography().equals("Mono")) {
        System.out.println("hdfhd");
    }

    if (obj1.getBranchClass().equalsIgnoreCase(obj2.getBranchClass())) {
        return this.similarBranchComparison(obj1, obj2);
    }
    else {
        // Different branches
        final int x = this.differentBranchesComparison(obj1, obj2);
        return x;
    }

}

private int differentBranchesComparison(final Geography obj1,
        final Geography obj2) {

    if ((obj1.getZip().equals("89420") && obj1.getParentNodeId().equals("Mono"))
            || ((obj2.getZip().equals("89420") && obj2.getParentNodeId().equals("Mono")))) {
        System.out.println("hdfhd");
    }

    // Same states - Obj1 is state
    if (obj1.getBranchClass().equalsIgnoreCase(ASDGeographyBasedDashboardVO.STATE_LEVEL)
            && obj1.getState().equalsIgnoreCase(obj2.getState())) {
        // obj2 should be greater
        return -1;
    }
    // Same states - Obj2 is state
    else if (obj2.getBranchClass().equalsIgnoreCase(ASDGeographyBasedDashboardVO.STATE_LEVEL)
            && obj1.getState().equalsIgnoreCase(obj2.getState())) {
        // obj1 should be greater
        return 1;
    }
    // Different states - obj1 OR Obj2 is state
    else if (((obj1.getBranchClass().equalsIgnoreCase(ASDGeographyBasedDashboardVO.STATE_LEVEL)) || (obj2
            .getBranchClass().equalsIgnoreCase(ASDGeographyBasedDashboardVO.STATE_LEVEL)))
            && !(obj1.getState().equalsIgnoreCase(obj2.getState()))) {
        // Delegate to state comparison
        return new CompareToBuilder().append(obj1.getState(), obj2.getState()).toComparison();
    }
    // Same states - Same counties (County - Zip)
    else if (obj1.getBranchClass().equalsIgnoreCase(ASDGeographyBasedDashboardVO.COUNTY_LEVEL)
            && ((obj1.getState().equalsIgnoreCase(obj2.getState())) && (obj1.getGeography()
                    .equalsIgnoreCase(obj2.getParentNodeId())))) {
        // obj2 (zip) should be greater
        return -1;
    }
    // Same states - Same counties (Zip - County)
    else if (obj2.getBranchClass().equalsIgnoreCase(ASDGeographyBasedDashboardVO.COUNTY_LEVEL)
            && ((obj1.getState().equalsIgnoreCase(obj2.getState())) && (obj1.getParentNodeId()
                    .equalsIgnoreCase(obj2.getGeography())))) {
        // obj1 should be greater
        return 1;
    }
    // Same states different counties (County - zip)
    else if ((obj1.getBranchClass().equalsIgnoreCase(ASDGeographyBasedDashboardVO.COUNTY_LEVEL))
            && (obj1.getState().equalsIgnoreCase(obj2.getState()) && !(obj1.getGeography()
                    .equalsIgnoreCase(obj2.getParentNodeId())))) {
        return new CompareToBuilder().append(obj1.getGeography(), obj2.getParentNodeId()).toComparison();
    }

    // Same states different counties (Zip - County)
    else if ((obj2.getBranchClass().equalsIgnoreCase(ASDGeographyBasedDashboardVO.COUNTY_LEVEL))
            && (obj1.getState().equalsIgnoreCase(obj2.getState()) && !(obj1.getParentNodeId()
                    .equalsIgnoreCase(obj2.getGeography())))) {
        return new CompareToBuilder().append(obj1.getParentNodeId(), obj2.getGeography()).toComparison();
    }

    // Different States
    else if (((obj1.getBranchClass().equalsIgnoreCase(ASDGeographyBasedDashboardVO.COUNTY_LEVEL)) || (obj2
            .getBranchClass().equalsIgnoreCase(ASDGeographyBasedDashboardVO.COUNTY_LEVEL)))
            && !(obj1.getState().equalsIgnoreCase(obj2.getState()))) {
        return new CompareToBuilder().append(obj1.getState(), obj2.getState()).toComparison();
    }
    return 0;

}

private int similarBranchComparison(final Geography obj1,
        final Geography obj2) {
    // State-State, County - County, Zip-Zip
    // State-State
    if (obj1.getBranchClass().equalsIgnoreCase(ASDGeographyBasedDashboardVO.STATE_LEVEL)) {
        return new CompareToBuilder().append(obj1.getState(), obj2.getState()).toComparison();
    }
    // County - County
    else if (obj1.getBranchClass().equalsIgnoreCase(ASDGeographyBasedDashboardVO.COUNTY_LEVEL)) {
        if (obj1.getState().equalsIgnoreCase(obj2.getState())) {
            // Compare Counties within the same state
            return new CompareToBuilder().append(obj1.getGeography(), obj2.getGeography()).toComparison();
        }
        else {
            // Compare Counties within different states
            return new CompareToBuilder().append(obj1.getState(), obj2.getState()).toComparison();
        }
    }
    else {
        // Zip - Zip
        if (obj1.getState().equalsIgnoreCase(obj2.getState())) {
            if (obj1.getParentNodeId().equalsIgnoreCase(obj2.getParentNodeId())) {
                return new CompareToBuilder().append(obj1.getZip(), obj2.getZip()).toComparison();
            }
            else {
                return new CompareToBuilder().append(obj1.getParentNodeId(), obj2.getParentNodeId())
                        .toComparison();
            }
        }
        else {
            // Compare Zip codes within different states
            return new CompareToBuilder().append(obj1.getState(), obj2.getState()).toComparison();
        }

    }
}
};

Solution

  • This should a simple comparator where you first compare state, then county, then zip. So this assumes you can write getState(), getCounty(), and getZip() methods, and you can write a compare for state, county, and zip. If you cannot get the state from all the different types, then you cannot compare them.

    Here's some pseudo-code.

    Comparator<Geography> comparator = new Comparator<>() {
        public int compare(final Geography obj1, final Geography obj2) {
            state1 = getState(obj1);
            state2 = getState(obj2);
    
            int retCode = state1.compare(state2);
            if (retCode != 0)
                return retCode;
    
            county1 = getCounty(obj1);
            county2 = getCounty(obj2);
    
            retCode = county1.compare(county2);
            if(retCode != 0)
               return retCode;
    
            zip1 = getZip(obj1);
            zip2 = getZip(obj2);
    
            retCode = zip1.compare(zip2);
            return retCode;
       }
    }