java - 如何创建具有动态规则的比较器?
问题描述
我需要根据按优先级排序的过滤器列表对项目列表进行排序。但是,这些过滤器来自 API 请求正文,因此它们可以更改。
我有一个过滤器类
public class Filter {
private String fieldName;
private String order;
// Getters and Setters...
}
一些过滤器对象
Filter filter1 = new Filter("price", "desc");
Filter filter2 = new Filter("size", "asc");
我的 Item 类是这样的:
public class Item {
private String productName;
private double size;
private double price;
// Getters and Setters...
}
然后我必须像这样对项目进行排序:
如果一个 Item.price 等于下一个 Item,比较它们的大小,依此类推...
我已经尝试为每个过滤器创建一个比较器,但是我无法链接它们,所以每个过滤器都对它自己的列表进行排序,而不考虑以前的排序方法(有时将整个列表倒置)。
我还尝试在 Item 类上实现 Comparable 接口,但接口方法compareTo
只接受一个参数(下一个 Item),而不接受规则列表。
所以给定一个项目列表,比如
List<Item> items = new ArrayList<Item>(
new Item("foo", 10.0, 5.0),
new Item("bar", 6.0, 15.0),
new Item("baz", 7.0, 5.0)
);
还有一个过滤器列表,例如
List<Filter> filters = new ArrayList<Filter>(
new Filter("price", "desc"),
new Filter("size", "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)
);
你能帮帮我吗?提前致谢!
重要提示:我对字段本身的比较没有问题。我的问题是制作一个动态比较器,它根据过滤器列表更改其比较。
解决方案
我相信以下内容应该将您推向正确的方向,将比较器链接到给定变量过滤器比较的项目。它使用反射来调用 getter 并假设比较是双精度数。
如果不能保证它们是双精度的,那么调整反射投射以投射到适用于所有用例的东西。
PropertyUtils.getProperty() 是 Apache Commons BeanUtils 的一部分,可以通过您选择的获取值来替换,无论是通过反射还是静态比较器。
public class Filter {
// properties, constructors, getters, setters ...
public Comparator<Item> itemComparator() {
return (item1, item2) -> {
Double val1 = (Double) PropertyUtils.getProperty(item1, fieldName);
Double val2 = (Double) PropertyUtils.getProperty(item2, fieldName);
return (order.equals("asc") ? val1.compareTo(val2) : val2.compareTo(val1);
};
}
public static Comparator<Item> chainedItemComparators(List<Filter> filters) {
return filters.stream()
.map(Filter::itemComparator)
.reduce((item1, item2) -> 0, (f1, f2) -> f1.thenComparing(f2));
}
}
然后使用链式比较器:
public static void main(String[] args) {
List<Filter> filters = new ArrayList<>(Arrays.asList(
new Filter("price", "desc"),
new Filter("size", "asc")
));
List<Item> items = new ArrayList<>(Arrays.asList(
new Item("bar", 6.0, 15.0),
new Item("baz", 7.0, 5.0),
new Item("foo", 10.0, 5.0)
));
items.sort(Filter.chainedItemComparators(filters));
}
推荐阅读
- javascript - 为什么这些 javascript 对象是相等的?
- javascript - 如何处理动态链接网址?
- node.js - 面临在实时服务器上上传构建的问题
- amazon-web-services - 来自 Spark 的 S3 写入间歇性失败,错误代码为 404 NoSuchKey
- sql - 我如何在我的 PostgreSQL 数据库中调用另一个过程
- dependency-injection - @BindsInstance 上的 @Singleton
- amazon-web-services - 未知动态 url 路径上的 AWS 应用程序负载均衡器
- r - 如何在R中使用应用函数组来计算带有加号分隔符的值的平均值
- asp.net-web-api2 - Web API 一项操作有效,而几乎相同的操作无效?
- typescript - 关于 import * as x from vs import x from 的说明