I'm trying to achieve sql like sorting for each attribute for a list of objects. Some thing like this - but with java
SELECT Id, CompanyName, City, Country FROM Supplier WHERE Country IN ('USA', 'Japan', 'Germany') ORDER BY Country ASC, CompanyName DESC
I have looked into/used libraries like ComparisonChain, lambdaj to acheive this behavior. But both lack the feature to add multiple sort orders like SQL. sorting country as ascending and name as descending. I have even tried to write my own code where; based on the sort value I send the -ve of the return value but for some reason that doesn't give the desired result.
public int compare(Item a, Item b)
{
int compareOwner = a.getOwner().compareTo(b.getOwner());
int compareCreated = a.getCreationTime().compareTo(b.getCreationTime());
Map<String, Integer> compareMap = new HashMap<String, Integer>();
compareMap.put("user", compareOwner);
compareMap.put("creationTime", compareCreated);
Map<String, Object> map = a.getProperties();
for (Map.Entry<String, Object> ent : map.entrySet())
{
if (b.getCustomProperties().containsKey(ent.getKey()))
{
Object a1 = ent.getValue();
Object b1 = b.Properties().get(ent.getKey());
if (a1 instanceof String && b1 instanceof String)
{
String val = (String) ent.getValue();
int cmp = val.compareTo((String) b.getCustomProperties().get(ent.getKey()));
compareMap.put(ent.getKey(), cmp);
}
else if (a1 instanceof Integer && b1 instanceof Integer)
{
Integer val = (Integer) ent.getValue();
int cmp = val.compareTo((Integer) b.getCustomProperties().get(ent.getKey()));
compareMap.put(ent.getKey(), cmp);
}
else if (a1 instanceof Float && b1 instanceof Float)
{
Float val = (Float) ent.getValue();
int cmp = val.compareTo((Float) b.getCustomProperties().get(ent.getKey()));
compareMap.put(ent.getKey(), cmp);
}
else if (a1 instanceof Double && b1 instanceof Double)
{
Double val = (Double) ent.getValue();
int cmp = val.compareTo((Double) b.getCustomProperties().get(ent.getKey()));
compareMap.put(ent.getKey(), cmp);
}
else if (a1 instanceof Date && b1 instanceof Date)
{
Date val = (Date) ent.getValue();
int cmp = val.compareTo((Date) b.getCustomProperties().get(ent.getKey()));
compareMap.put(ent.getKey(), cmp);
}
}
}
int returnValue = 0;
for (Map.Entry<String, Boolean> entry : fields.entrySet())
{
if (compareMap.get(entry.getKey()) != null && compareMap.get(entry.getKey()) == 0)
{
continue;
}
else if (compareMap.get(entry.getKey()) != null)
{
if (entry.getValue() == false)
{
return returnValue = -returnValue;
}
return returnValue = compareMap.get(entry.getKey());
}
else
{
continue;
}
}
return returnValue;
}
Where the fields variable is map of attributes and their corresponding orders.
Are there any alternative libraries or anyway to improve this comparator to support multi ordering.
Comparator.comparing(...).thenComparing(...)be enough?ComparatorAPI to sort by multiple attributes. Based on your user's selection, you can chain more or less attributes to it.Comparator. They are quite new, and they offer some factory methods, reversing, natural order, custom order... It is really very cool how short and nice to read those comparators can become. It takes some practise, though. Don't hesitate to update your question if you get stuck.