仅根据字段名称对类数组进行排序

Jas*_*son 2 java sorting reflection

我有一个应用程序,其中用户为我提供了一个字段的名称,例如nameor 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

还有我的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
    }
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,该Arrays.sort()行导致编译时错误消息Capture of ? instead of Object。我曾尝试铸造的第二个参数Comparable<?>Comparable<? super sorterField.getType()等等,没有运气。想法?

Qwe*_*ken 6

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));
}
Run Code Online (Sandbox Code Playgroud)