java - 仅根据字段名称对类数组进行排序
问题描述
我有一个应用程序,其中用户向我提供了一个字段的名称,例如name
or costInCents
,我必须按该字段排序。我有办法保证字段名称是正确的。此应用程序导致我根本无法创建我的类Comparable
并实现特定的复杂性compareTo()
,因为通过自定义实现,compareTo()
我需要知道在实现时要使用哪些字段/方法。
因此,为了实现这个目标,我尝试使用反射来将字段与其访问器匹配。这是我想做的MWE。
ClassProduct
是一个简单的 POJO 类,我想对其实例进行成对比较:
public class Product
{
final String name;
final Integer quantity;
final Long costInCents;
public Product(final String name, final Integer quantity, final Long costInCents)
{
this.name = name;
this.quantity = quantity;
this.costInCents = costInCents;
}
public String getName()
{
return name;
}
public Integer getQuantity()
{
return quantity;
}
public Long getCostInCents()
{
return costInCents;
}
}
还有我的Main
课,目前不完整:
public class Main {
public static void main(String[] args) {
final Product[] productArray =
{
new Product("Clorox wipes", 50, 700L),
new Product("Desk chair", 10, 12000L),
new Product("TV", 5, 30000L),
new Product("Bookcase", 5, 12000L),
new Product("Water bottle", 20, 700L),
};
// The following void methods are supposed to sort in-place with something like Arrays.sort() or Collections.sort(),
// but I am also open to solutions involving stuff like Stream::sorted() or similar ones, which return a sorted array.
sortByField(productArray, "costInCents");
sortByField(productArray, "name");
}
private void sortByField(final Product[] productArray, final String sorterFieldName)
{
final Field sorterField = getSorterField(sorterFieldName, LiteProduct.class); // Gets the Field somehow
final Method sorterAccessor = getSorterAccessor(sorterField, LiteProduct.class); // Given the Field, this is easy
Arrays.sort((Product p1, Product p2)->((Comparable<?>)sorterAccessor.invoke(p1)).compareTo(sorterAccessor.invoke(p2)) > 0); // Capture of ? instead of Object
}
}
不幸的是,该Arrays.sort()
行导致带有 message 的编译时错误Capture of ? instead of Object
。我尝试将第二个参数转换为Comparable<?>
,Comparable<? super sorterField.getType()
等,但没有成功。想法?
解决方案
可能是最好的方法 - 使用排序策略。无需反射,兼容更复杂的排序逻辑:
Map<String, Comparator<Product>> sortingStrategies = new HashMap<>(){
{
put("costInCents", Comparator.comparingLong(p->p.costInCents));
put("quantity", Comparator.comparingLong(p->p.quantity));
put("name", Comparator.comparing(p->p.name));
}
};
private void sortByField(final Product[] productArray, final String sorterFieldName)
{
Arrays.sort(productArray, sortingStrategies.get(sorterFieldName));
}
推荐阅读
- python - 请求HTML为 text/html
- javascript - 使用 cssText 切换元素
- apache - Shiro Annotation 不适用于带有 Jersey REST 和 JDBC Realm 的 Spring Boot 2.0.4
- javascript - node-api 内的 SQlite 池连接
- javascript - 如果仅存在 1 个管理员而不显示对话框,则删除按钮会刷新页面。我错过了什么?
- json - 如何在服务器端接收带有音频文件和文件信息的 Json 对象(Spring 启动控制器)
- python-2.7 - 如何将 SVM 类概率转换为 logits?
- html - 在移动模式下更改网格列顺序
- javascript - 获取 vanilla JS 中选择元素的前面(初始)和所选值
- python - 尝试加入并获取 select_related 中给出的无效字段名称:'audio_links'。选项有:(无)