仅根据字段名称对类数组进行排序 [英] Sorting an array of classes based only on field name
问题描述
我有一个应用程序,其中用户为我提供了一个字段的名称,例如 name
或 costInCents
,我必须按该字段排序.我有办法保证字段名称是正确的.这个应用程序导致了我无法让我的类 Comparable
并实现特定的 compareTo()
的复杂性,因为使用 compareTo()
我需要知道在实现时使用哪些字段/方法.
I have an application where a user provides me with the name of a field, e.g name
or costInCents
, and I have to sort by that field. I have ways of guaranteeing that the field name will be correct. This application causes the complication that I simply cannot make my class Comparable
and implement a specific compareTo()
, since with a custom implementation of compareTo()
I need to know which fields / methods to use at implementation time.
所以为了实现这个目标,我尝试使用反射来将字段与其访问器相匹配.这是我想做的事情的 MWE.
So to achieve this goal, I am trying to use reflection in order to match the field to its accessor. Here's a MWE of what I want to do.
Class Product
是一个简单的 POJO 类,我想对它的实例进行成对比较:
Class Product
is a simple POJO class whose instances I want to pairwise compare:
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
类,目前还没有完成:
And my Main
class, which is currently incomplete:
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()
行导致编译时错误,消息 Capture of ?而不是对象
.我尝试将第二个参数转换为 Comparable>
, Comparable 等,没有运气.想法?
Unfortunately, the Arrays.sort()
line results in a compile-time error with message Capture of ? instead of Object
. I have tried casting the second argument to Comparable<?>
, Comparable<? super sorterField.getType()
, etc, with no luck. Ideas?
推荐答案
可能是最好的方法 - 使用排序策略.无需反射,兼容更复杂的排序逻辑:
Possibly the best way - with sorting strategies. No need for reflection, compatible with more complex sorting logic:
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));
}
这篇关于仅根据字段名称对类数组进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!