java - 按属性对集合进行排序,以字符串形式给出

标签 java reflection nashorn

我正在为 jQuery 数据表实现服务器端处理。对于那些不熟悉它的人来说,该插件允许您对列进行升序/降序排序,以及使用单个文本框搜索所有列。由于我的对象列表太大而无法发送到客户端,因此我需要通过 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;
}

我也涉足了 Reflection,但目前还不完整。

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;
        });

    }

我的两种方法都感觉像是黑客,有没有标准的方法来实现这一点?

最佳答案

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

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"));
}

关于java - 按属性对集合进行排序,以字符串形式给出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42349746/

相关文章:

java - Spring数据聚合查询elasticsearch

java - 带有图像背景和文本对齐的 JButton

asp.net - 在 F# 中,如何判断对象是否为 Async<_>,以及如何将其转换为 Async<_>?

javascript - 为什么 Java 8 Nashorn (JavaScript) 模返回 0.0( double )而不是 0(整数)?

Java Nashorn 引擎 ArrayNode 处理

java - 使用大 o 合并和排序 2 个排序数组寻求澄清。

java - 为什么这样不会短路呢?

Java getMethods() 与继承层次结构相关

go - 如何在 Go 中获取结构的方法列表?

Java,nashorn访问另一个js文件