【问题标题】:Dynamic Sorting with multiple Criteria field in JavaJava中具有多个条件字段的动态排序
【发布时间】:2019-05-07 20:31:39
【问题描述】:

我需要使用动态搜索条件列表对动态对象列表进行排序。所以我有一个接受的方法

sort(List<SortCriterion> sortCriteria, List<T> searchList){

}

现在,如果我有一个如下所示的 TradeOperator 对象列表。我可以在 sort 方法中发送其他对象,例如 CarOperator。

 public class TradeOperator implements SearchResult{

      private String name;
      private String address;
      private String status;
      private Long   regNum;
      private Double price;
}

SortCriterion 代码如下所示。

 public class SortCriterion{

       protected String field;   
       protected String direction;
    }

字段可以是 TradeOperator.name,方向 = ASC 或 DESC。现在我可以传递具有多个字段和方向的 SortCriterion 列表。

这就是我所做的。我在 MAP sortValues 中收集了所有 ASC 字段和所有 DESC 字段,其中 Key = ASC 和 DESC 和值是字段列表。然后在 ASC 中排序,然后以相反的顺序。

sort(List<SortCriterion> sortCriteria, List<T> searchList){
   Map<String, Set<String>> sortValues = new HashMap<>();
    populateSortedValues(sortCriteria, "ASC", sortValues);//group fields on ASC or DESC as key = ASC and Value = List of Fields
    populateSortedValues(sortCriteria, "DESC", sortValues);

    if (null != sortValues.get(Constants.ASC_ORDER))
    {
        for (String ascendingOrder : 
         sortValues.get(Constants.ASC_ORDER))
        {
        Collections.sort(list, new SearchResultComparator(ascendingOrder));
        }
    }

    if (null != sortValues.get(Constants.DESC_ORDER))
    {
        for (String descOrder : sortValues.get(Constants.DESC_ORDER))
        {
        Collections.sort(list, new 
               SearchResultComparator(descOrder).reversed());
        }
    }
}

这里是 SearchResultComparator 类。

public class SearchResultComparator implements Comparator<Object> {

private String getter;


public SearchResultComparator(String field) {
    this.getter = "get" + field.substring(0, 1).toUpperCase() + field.substring(1);

}

@SuppressWarnings("unchecked")
public int compare(Object o1, Object o2) {
    try {
        if (o1 != null && o2 != null) {
            o1 = o1.getClass().getMethod(getter, new Class[0]).invoke(o1, new Object[0]);
            o2 = o2.getClass().getMethod(getter, new Class[0]).invoke(o2, new Object[0]);
            if(isDouble(o1.toString()) && isDouble(o2.toString())){
                Double d1 =  Double.parseDouble(o1.toString());
                Double d2 =  Double.parseDouble(o2.toString());
                return (d1 == null) ? -1 : ((d2 == null) ? 1 : ((Comparable<Double>) d1).compareTo(d2));
            }
        }
    } catch (Exception e) {
        throw new SystemException("Cannot compare " + o1 + " with " + o2 + " on " + getter, e);
    }

        return (o1 == null) ? -1 : ((o2 == null) ? 1 : ((Comparable<Object>) o1).compareTo(o2));


}

public boolean isDouble(String value)
{
try
{
    Double.parseDouble(value);
    return true;
}
catch (NumberFormatException e)
{
    return false;
}
}

}

它以一种方式排序。如果我对 ASC 中的一个字段进行排序,那么 DESC 中的另一个字段 ASC 排序就会丢失。请帮忙。我是 Java 新手。

【问题讨论】:

  • 如果您确实是 Java 新手,那么您可能已经不知所措了。在您介绍它时,您的任务需要使用反射(实际上您正在使用),而反射不是一个非常适合新手的主题。这不是从更简单的东西开始的唯一原因,但这已经足够了。
  • 一目了然,您似乎正在尝试为 HashMap 中的键添加多个值。地图无法做到这一点。相反,他们只是丢弃旧值并采用新值。
  • ASC 和 DESC 映射工作正常,唯一的问题是如果我们发送多个 SortCriterion,同时使用 ASC 和 DESC 它需要 DESC 排序,而 ASC 排序消失了。我很想在 DB 中排序,但我们不能修改任何查询。

标签: java sorting dynamic criteria


【解决方案1】:

您不需要 SearchResultComparator 或分离 ASC 和 DESC。使用此技术对任意顺序进行链式排序。

sort(List<SortCriterion> sortCriteria, List<T> list) {
    Collections.sort(list, new Comparator<T>() {
        public int compare(T one, T two) {
            CompareToBuilder compToBuild = new CompareToBuilder();
            sortCriteria.stream().forEachOrdered(sc -> {
                String fieldName = sc.getField();
                String direction = sc.getDirection();
                String fv1 = getFieldValue(fieldName, one);
                String fv2 = getFieldValue(fieldName, two);
                if(direction.equals("ASC")) {
                    compToBuild.append(fv1, fv2);
                }
                if(direction.equals("DESC")) {
                    compToBuild.append(fv2, fv1);
                }
            });
            return compToBuild.toComparison();
        }
    });
}

使用反射获取字段值

private String getFieldValue(String fieldName, T object) {
    Field field;
    try {
        field = object.getClass().getDeclaredField(fieldName);
    } catch (NoSuchFieldException e) {
        logger.error(e);
        return null;// or ""
    }
    field.setAccessible(true);
    try {
        return (String) field.get(object);
    } catch (IllegalAccessException e) {
        logger.error(e);
        return null;// or ""
    }
}

【讨论】:

    猜你喜欢
    • 2018-03-30
    • 1970-01-01
    • 2022-11-29
    • 2016-12-23
    • 1970-01-01
    • 2020-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多