0

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.

stackMan10
  • 732
  • 6
  • 25
  • Could you explain, in natural language, what you are trying to achieve? And some example data would be great. So far, I do not see the need for a custom implementation. Wouldn't `Comparator.comparing(...).thenComparing(...)` be enough? – Malte Hartwig Jan 11 '18 at 13:42
  • I am trying to sort a list of objects based on multiple attributes, like name, creationDate, id; basically any attribute selected by the user. And the user has an option to select the order for each of these attributes. Name as asc, creationDate as descending, id as ascending. An sql query can do this as shown above. I want to achieve the same thing using java code – stackMan10 Jan 11 '18 at 13:48
  • Ok. Look at [this answer to a related question](https://stackoverflow.com/a/33326770/7653073). It shows how to use the `Comparator` API to sort by multiple attributes. Based on your user's selection, you can chain more or less attributes to it. – Malte Hartwig Jan 11 '18 at 13:51
  • I'll give this a try. My main concern is would multi ordering work, for attributes with descending order; I return negative value of the compare value? – stackMan10 Jan 11 '18 at 13:56
  • look at the (static) methods in `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. – Malte Hartwig Jan 11 '18 at 14:02

0 Answers0