Java 如何创建具有动态规则的比较器?

Java 如何创建具有动态规则的比较器?,java,sorting,dynamic,comparator,comparable,Java,Sorting,Dynamic,Comparator,Comparable,我需要根据过滤器列表对项目列表进行排序,过滤器列表按优先级排序。但是,这些过滤器来自API请求主体,因此它们可以更改 我有一个过滤器类 公共类过滤器{ 私有字符串字段名; 私有字符串顺序; //接球手和接球手。。。 } 一些过滤对象 过滤器过滤器1=新过滤器(“价格”、“说明”); 过滤器过滤器2=新过滤器(“尺寸”、“asc”); 我的Item类如下所示: 公共类项目{ 私有字符串产品名称; 私人双户型; 私人双价; //接球手和接球手。。。 } 然后我必须对项目进行如下排序: 如果一个

我需要根据过滤器列表对项目列表进行排序,过滤器列表按优先级排序。但是,这些过滤器来自API请求主体,因此它们可以更改

我有一个过滤器类

公共类过滤器{
私有字符串字段名;
私有字符串顺序;
//接球手和接球手。。。
}
一些过滤对象

过滤器过滤器1=新过滤器(“价格”、“说明”);
过滤器过滤器2=新过滤器(“尺寸”、“asc”);
我的Item类如下所示:

公共类项目{
私有字符串产品名称;
私人双户型;
私人双价;
//接球手和接球手。。。
}
然后我必须对项目进行如下排序:

如果一个Item.price等于下一个Item,比较它们的大小,依此类推

我已经尝试为每个过滤器创建一个比较器,但我无法链接它们,因此每个过滤器都会自己对列表进行排序,而不考虑前面的排序方法(有时会将整个列表颠倒)

我还尝试在Item类上实现Comparable接口,但是接口方法
compareTo
只接受单个参数(下一项),而不接受规则列表

所以给出了一个项目列表,比如

List items=new ArrayList(
新项目(“foo”、10.0、5.0),
新项目(“bar”、6.0、15.0),
新项目(“baz”、7.0、5.0)
);
还有一个过滤器列表,如

List filters=new ArrayList(
新过滤器(“价格”、“说明”),
新过滤器(“尺寸”、“asc”)
);
我希望结果是

List<Item> sortedItems = new ArrayList<Item>(
  new Item("bar", 6.0, 15.0),
  new Item("baz", 7.0, 5.0),
  new Item("foo", 10.0, 5.0)
);
List sortedItems=新建ArrayList(
新项目(“bar”、6.0、15.0),
新项目(“baz”、7.0、5.0),
新项目(“foo”,10.0,5.0)
);
你能帮帮我吗?提前谢谢


重要提示:我对字段本身的比较没有问题。我的问题是创建一个动态比较器,根据过滤器列表更改其比较。

给定基于价格和基于大小的初始实现,您可以组合比较器

以下方法为给定筛选器创建项目比较器:

//Preferring static implementations to reflection-based ones
//if there are too many fields, you may want to use a Map<String, Comparator<Item>>
static Comparator<Item> priceComparator = Comparator.comparing(Item::getPrice);
static Comparator<Item> sizeComparator = Comparator.comparingDouble(Item::getSize);

private static Comparator<Item> itemComparator(Filter filter) {
    Comparator<Item> comparator = "price".equals(filter.getFieldName()) ? 
                                     priceComparator : sizeComparator;

    if ("desc".equals(filter.getOrder()))
        return comparator.reversed();

    return comparator;
}

我相信下面的内容应该会将您推向正确的方向,为给定的变量过滤器比较项链接比较器。它使用反射调用getter,并假设比较是双精度的

如果不能保证它们是双倍的,那么调整反射模式,使其适用于所有用例

getProperty()是ApacheCommonsBeanutils的一部分,可以通过选择获取值来替换,无论是通过反射还是静态比较器

公共类过滤器{
//属性、构造函数、getter、setter。。。
公共比较器itemComparator(){
返回(项目1、项目2)->{
Double val1=(Double)PropertyUtils.getProperty(item1,fieldName);
Double val2=(Double)PropertyUtils.getProperty(item2,fieldName);
返回(order.equals(“asc”)?val1.compareTo(val2):val2.compareTo(val1);
};
}
公共静态比较器chainedItemComparators(列表过滤器){
返回filters.stream()
.map(筛选器::itemComparator)
.减少((第1项,第2项)->0,(f1,f2)->f1。然后比较(f2));
}
}
然后使用链式比较器:

publicstaticvoidmain(字符串[]args){
列表过滤器=新的ArrayList(Arrays.asList(
新过滤器(“价格”、“说明”),
新过滤器(“尺寸”、“asc”)
));
列表项=新建ArrayList(Arrays.asList(
新项目(“bar”、6.0、15.0),
新项目(“baz”、7.0、5.0),
新项目(“foo”,10.0,5.0)
));
项目.排序(过滤器.chainedItemComparators(过滤器));
}
也可以用于链式比较器
public static void main(String args[]) {

    Comparator<Item> comparator = itemComparator(filters.get(0));
    for (Filter f : filters.subList(1, filters.size())) {
        comparator = comparator.thenComparing(itemComparator(f));
    }

    items.sort(comparator);
}
[[productName=bar, size=6.0, price=15.0],
 [productName=baz, size=7.0, price=5.0],
 [productName=foo, size=10.0, price=5.0]]