Search code examples
javadictionarytreemap

TreeMap doesn't work for some of keys


I'm implementing a TreeMap in java today to track the navigation for next page. I have 5 entries in the treemap, 3 of them works while 2 don't work.

NavigationHelper.java :

public class NavigationHelper {

private static String hhSection = HXConstants.CSR_SECTION_FAMILY_DETAILS;
private static String[] hhPages = {
        HXConstants.CSR_PAGE_ID_HOUSEHOLD_MEMBERS, 
            HXConstants.CSR_PAGE_ID_HOUSEHOLD_RELATIONSHIP, 
                HXConstants.CSR_PAGE_ID_HOUSEHOLD_ADDITIONAL_QUESTIONS,
                    HXConstants.CSR_PAGE_ID_HOUSEHOLD_SUMMARY_NEW,
                        HXConstants.CSR_PAGE_ID_HOUSEHOLD_PRIVACY_AGREEMENT
};
private static String hhPath = "household";
public static HashMap<String, NavLocation> getHHNavMap()
{

    HashMap<String, NavLocation> hhNavMap = new HashMap<String, NavLocation>();
    for (int i=0;i<hhPages.length;i++ ) {
        hhNavMap.put(hhPath+"/"+hhPages[i], new NavLocation(hhSection,hhPages[i]));
    }
    return hhNavMap;
}

public static Map<NavLocation,String> getHHBackNavMap() {
    TreeMap<NavLocation,String> hhBackNavMap = new TreeMap<NavLocation, String>();
    HashMap<String, NavLocation> hhNavMap = getHHNavMap();
    for(Entry<String, NavLocation> entry : hhNavMap.entrySet()) {
        hhBackNavMap.put(entry.getValue(), entry.getKey());
    }
    return hhBackNavMap;
}


public static class NavLocation implements Comparable<NavLocation>{
    private String section;
    public NavLocation(String s, String p) {
        this.section = s;
        this.page = p;
    }
    public String getSection() {
        return section;
    }

    public String getPage() {
        return page;
    }
    private String page;

    @Override
    public int compareTo(NavLocation navObj) {
        if(navObj.getPage().equals(this.page) && (navObj.getSection().equals(this.section)))
            return 0;
        return 1;
    }

}
}

AppAggNavigationHelper.java :

public class AppAggNavigationHelper extends RestServiceBaseTest {

private static String hhSection = HXConstants.CSR_SECTION_FAMILY_DETAILS;
private static String[] hhPages = {
        HXConstants.CSR_PAGE_ID_HOUSEHOLD_MEMBERS, 
            HXConstants.CSR_PAGE_ID_HOUSEHOLD_RELATIONSHIP, 
                HXConstants.CSR_PAGE_ID_HOUSEHOLD_ADDITIONAL_QUESTIONS,
                    HXConstants.CSR_PAGE_ID_HOUSEHOLD_SUMMARY_NEW,
                        HXConstants.CSR_PAGE_ID_HOUSEHOLD_PRIVACY_AGREEMENT
};

NavigationHelper navigationHelper = new NavigationHelper();
List<NavLocation> navList = new ArrayList<NavLocation>();

@Before
public void populateNavLocations() {
    for(int i = 0 ; i < hhPages.length ; i++) {
        navList.add(new NavLocation(hhSection, hhPages[i]));
    }
}

@Test
public void test() {
    testWithoutRest();
}



public void testWithoutRest() {
    TreeMap<NavLocation,String> map = (TreeMap<NavLocation, String>) navigationHelper.getHHBackNavMap();
    for(Map.Entry<NavLocation, String> entry : map.entrySet()) {
        NavLocation nav = entry.getKey();
        System.out.println(nav.getPage() + " " + nav.getSection());
        System.out.println(entry.getValue());

    }
    p("*****");
    for(NavLocation navLocation : navList) {
        System.out.println(navLocation.getPage() + " " + navLocation.getSection() + " " + map.get(navLocation));
    }
}
}

Then the output is wired, for member, summary, privacy it's working. But for relation and questions it's not. :

member familydetails household/member

relation familydetails null

question familydetails null

summary familydetails household/summary

privacy familydetails household/privacy

Why relation and question are not working?


Solution

  • Your compareTo method is broken. If two NavLocation objects, a and b differ in their page or section, both a.compareTo(b) and b.compareTo(a) will return 1, thus violating the general contract of the method, which may lead to unexpected results.

    Instead, the classic way to implement such a method depending on the objects properties would probably look something like this:

    @Override
    public int compareTo(NavLocation other) {
        int result = getPage().compareTo(other.getPage());
        if (result != 0) {
            return result;
        }
    
        return getSection().compareTo(other.getSection());
    }