按属性对集合进行排序,以String形式给出

时间:2017-02-20 16:34:06

标签: java reflection nashorn

我正在为jQuery数据表实现服务器端处理。对于那些不熟悉它的人来说,插件允许您对列asc / desc进行排序,以及使用单个文本框搜索所有列。由于我的对象列表太大而无法发送到客户端,因此我需要通过Java复制它的排序功能。

这是我正在使用的对象。每个字段都是客户端表中的一列。所有字段都是字符串或基元/包装器。

public class MyObject{

    String id;
    String productType;
    String productGroup;

    double totalSales;
    double salesVariance;

    int vendorId;
    String vendorName;
}

我需要能够按任何字段排序,升序/降序,没有为每个字段硬编码比较器函数。

给定一个表示字段名称的字符串,我将如何实现通用排序功能?

我目前的解决方案是使用Nashorn处理列表......:)

调用Nashorn的Java方法:

/**
 * @param sortBy - field name
 * @param sortDirection - asc/desc
 */
public void applyFilteringChanges(List<MyObject> myObjects, String sortBy, String sortDirection) throws Exception{

    Invocable invocable = (Invocable) engine;
    invocable.invokeFunction("sortObjects", myObjects, sortBy, sortDirection);

}

Nashorn代码:

function sortObjects(myObjects, prop, direction) {
    var dir = (direction === 'asc') ? 1 : -1;
    myObjects.sort(function(a,b){
        return compare(a,b,prop) * dir;
    })
};

function compare(a,b,prop){
    if(a[prop] < b[prop])
        return -1;
    else if(a[prop] > b[prop])
        return 1;
    return 0;
}

我还涉足反思,但目前还不完整。

public void applyFilteringChanges(List<MyObject> myObjects, String sortBy, String sortDirection) throws Exception{

        myObjects.sort((s1,s2)->{
            Field field;
            try {
                field = s1.getClass().getDeclaredField(sortBy);
                Class<?> type = field.getType();
                if(type.isPrimitive()){
                    //deal with primitive
                }else{
                    Comparable o1FieldValue = (Comparable) field.get(s1);
                    Comparable o2FieldValue = (Comparable) field.get(s2);
                    return o1FieldValue.compareTo(o2FieldValue);
                }

            } catch (Exception e) {
                e.printStackTrace();
            }

            return 0;
        });

    }

我的两种方法都像黑客一样,是否有标准的方法来实现这一目标?

1 个答案:

答案 0 :(得分:0)

您可以像这样创建一个通用比较器:

class MyComparator<T extends MyObject> implements Comparator<T> {

    private String field;

    public MyComparator(String field) {
        this.field = field;
    }

    @Override
    public int compare(T o1, T o2) {
        switch (field) {
            case "id" :
                return o1.id.compareTo(o2.id);

            case "productType":
                return o1.productType.compareTo(o2.productType);

            case "productGroup":
                return o1.productGroup.compareTo(o2.productGroup);

            //...
        }
        return 0;
    }
}

像这样使用:

public static void main(String[] args)
{
    List<MyObject> objects = new ArrayList<>();

    Collections.sort(objects, new MyComparator<>("id"));
}