Search code examples
javalistsortingcomparator

How to sort List<Object> in a Map<String, Object> in Java?


I have two maps, Map<String,Object> which looks like:

Map<String, Object> map1 = {
    taxRate={rateType=EXCLUSIVE, rate=0.07}, 
    taxAmount={currencyCode=USD, amount=7.0},
    jurisdictionTaxes=[{jurisdictionLevel=State, taxAmount={currencyCode=USD, amount=null}, taxRate={rateType=EXCLUSIVE, rate=null}, displayName=, jurisdictionName=, responsiblePartyReason=}, {jurisdictionLevel=County, taxAmount={currencyCode=USD, amount=null}, taxRate={rateType=EXCLUSIVE, rate=null}, displayName=, jurisdictionName=, responsiblePartyReason=}, {jurisdictionLevel=City, taxAmount={currencyCode=USD, amount=null}, taxRate={rateType=EXCLUSIVE, rate=null}, displayName=, jurisdictionName=, responsiblePartyReason=}, {jurisdictionLevel=District, taxAmount={currencyCode=USD, amount=null}, taxRate={rateType=EXCLUSIVE, rate=null}, displayName=, jurisdictionName=, responsiblePartyReason=}],
    withholdingJurisdictionTaxes=[]
}

Map<String, Object> map2 = {
    taxRate={rateType=EXCLUSIVE, rate=0.07}, 
    taxAmount={currencyCode=USD, amount=7.0},
    jurisdictionTaxes=[{jurisdictionLevel=State, taxAmount={currencyCode=USD, amount=null}, taxRate={rateType=EXCLUSIVE, rate=null}, displayName=, jurisdictionName=, responsiblePartyReason=}, {jurisdictionLevel=County, taxAmount={currencyCode=USD, amount=null}, taxRate={rateType=EXCLUSIVE, rate=null}, displayName=, jurisdictionName=, responsiblePartyReason=}, {jurisdictionLevel=City, taxAmount={currencyCode=USD, amount=null}, taxRate={rateType=EXCLUSIVE, rate=null}, displayName=, jurisdictionName=, responsiblePartyReason=}, {jurisdictionLevel=District, taxAmount={currencyCode=USD, amount=null}, taxRate={rateType=EXCLUSIVE, rate=null}, displayName=, jurisdictionName=, responsiblePartyReason=}],
    withholdingJurisdictionTaxes=[]
}

I am comparing these two maps using

  Map<String, Object> flatMap1 = FlatMapUtil.flatten(map1);
  Map<String, Object> flatMap2 = FlatMapUtil.flatten(map2);
  MapDifference<String, Object> difference = Maps.difference(flatMap1, flatMap2);

However if you look at the second key value in the map, it is a list of objects. The order matters while calculating the diff. So I would need to sort that particular list before finding the Map.difference.

Can you help me understand how I can sort this List?

I tried the following:

1. Collections.sort(Arrays.asList(leftMap.get("jurisdictionTaxes")));

Error: Required type: List <T>
Provided: List <Object>

2. Arrays.asList(leftMap.get("jurisdictionTaxes")).sort((s1, s2) -> s1.get("jurisdictionLevel") - s2.get("jurisdictionLevel"));

Error: Cannot resolve method 'get' in 'Object'
 public static <K, V> MapDifference<K, V> difference(Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right) {
        if (left instanceof SortedMap) {
            SortedMap<K, ? extends V> sortedLeft = (SortedMap)left;
            return difference(sortedLeft, right);
        } else {
            return difference(left, right, Equivalence.equals());
        }
    }

Solution

  • I think that this is the key:

    Error: Required type: List <T>
    

    The sort needs a comparable class to sort with. Try this to sort the jurisdictionTaxes:

        Arrays.sort((JurisdictionTax[]) map1.get("jurisdictionTaxes"));
    

    Eg:

    static Map<String, Object> map1 = new HashMap<>();
    
    static {
        map1.put("taxRate", "rateType=EXCLUSIVE, rate=0.07");
        map1.put("taxAmount", "currencyCode=USD, amount=7.0");
        map1.put("jurisdictionTaxes", new JurisdictionTax[] { new JurisdictionTax(new TaxRate("bbb")),
                new JurisdictionTax(new TaxRate("aaa")) });
        map1.put("withholdingJurisdictionTaxes", "[]");
    }
    
    static Map<String, Object> map2 = new HashMap<>();
    
    static {
        map2.put("taxRate", "rateType=EXCLUSIVE, rate=0.07");
        map2.put("taxAmount", "currencyCode=USD, amount=7.0}");
        map2.put("jurisdictionTaxes", new JurisdictionTax[] { new JurisdictionTax(new TaxRate("ccc")),
                new JurisdictionTax(new TaxRate("aaa")) });
        map2.put("withholdingJurisdictionTaxes", "[]");
    }
    
    public static void main(String[] args) {
    System.out.println("map1 before: " + ((JurisdictionTax[])map1.get("jurisdictionTaxes"))[0]);
    System.out.println("map2 before: " + ((JurisdictionTax[])map2.get("jurisdictionTaxes"))[0]);
    
    Arrays.sort((JurisdictionTax[]) map1.get("jurisdictionTaxes"));
    Arrays.sort((JurisdictionTax[]) map2.get("jurisdictionTaxes"));
    
    System.out.println("map1 after: " + ((JurisdictionTax[])map1.get("jurisdictionTaxes"))[0]);
    System.out.println("map2 after: " +    ((JurisdictionTax[])map2.get("jurisdictionTaxes"))[0]);
    

    prints:

    map1 before: JurisdictionTax [jurisdictionLevel=null, taxAmount=null, taxRate=TaxRate [rateType=bbb, rate=null]]
    map2 before: JurisdictionTax [jurisdictionLevel=null, taxAmount=null, taxRate=TaxRate [rateType=ccc, rate=null]]
    map1 after: JurisdictionTax [jurisdictionLevel=null, taxAmount=null, taxRate=TaxRate [rateType=aaa, rate=null]]
    map2 after: JurisdictionTax [jurisdictionLevel=null, taxAmount=null, taxRate=TaxRate [rateType=aaa, rate=null]]
    

    With defined classes:

    public class JurisdictionTax implements Comparable<JurisdictionTax> {
    public JurisdictionTax(TaxRate taxRate) {
        super();
        this.taxRate = taxRate;
    }
    public String jurisdictionLevel;
    public TaxAmount taxAmount;
    public TaxRate taxRate;
    public String displayName;
    public String jurisdictionName;
    public String responsiblePartyReason;
    
    
    @Override
    public int compareTo(JurisdictionTax other) {
        // incomplete
        return this.taxRate.rateType.compareTo(other.taxRate.rateType);
    }
    
    
    @Override
    public String toString() {
        return "JurisdictionTax [jurisdictionLevel=" + jurisdictionLevel + ", taxAmount=" + taxAmount + ", taxRate="
                + taxRate + "]";
    }
        
    
    
    }
    

    etc