根据对象的参数化属性对对象列表进行排序 [英] Sort a list of objects based on a parameterized attribute of the object

查看:119
本文介绍了根据对象的参数化属性对对象列表进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们有一个具有以下属性的对象:

Assuming that we have an object with the following attributes:

public class MyObject {

    private String attr1;
    private Integer attr2;

    //...

    public String getAttr1() {
        return this.attr1;
    }

    public Integer getAttr2() {
        return this.attr2;
    }
}

排序列表的一种方法 mylist ,基于其属性 attr1 是:

One way of sorting a list mylist of this object, based on its attribute attr1 is:

mylist.sort(Comparator.comparing(MyObject::getAttr1));

是否可以动态方式在方法中使用此代码并替换 getAttr1 部分有一个方法,根据对象的名称返回对象属性的getter?类似于:

Is it possible to use this code inside a method in a dynamic way and replace the getAttr1 part with a method that returns the getter of an attribute of the object based on its name? Something like:

public void sortListByAttr(List<MyObject> list, String attr) {
    list.sort(Comparator.comparing(MyObject::getGetterByAttr(attr)));
}

MyObject :: getGetterByAttr(attr )部分不编译,我写的只是作为一个例子来解释我的想法

The MyObject::getGetterByAttr(attr) part does not compile, I wrote it just as an example to explain my idea

我试图实现一个方法以下代码新的PropertyDescriptor(attr,MyObject.class).getReadMethod()。invoke(new MyObject())但是仍然无法使用参数调用方法比较方法

I tried to implement a method with the following code new PropertyDescriptor(attr, MyObject.class).getReadMethod().invoke(new MyObject()) but It's still not possible to call a method with a parameter from the comparing method

推荐答案

你可以添加像

You could add a method like

public static Function<MyObject,Object> getGetterByAttr(String s) {
    switch(s) {
        case "attr1": return MyObject::getAttr1;
        case "attr2": return MyObject::getAttr2;
    }
    throw new IllegalArgumentException(s);
}

到您的班级,但返回的功能不适合 Comparator.comparing ,因为它期望类型实现 U扩展Comparable<?超级U> ,而 String 整数中的每一个都能够实现此约束一个单独的调用,没有办法为 getGetterByAttr 声明一个通用的返回类型,以允许两种类型并且仍然与比较的声明兼容

to your class, but the returned function is not suitable for Comparator.comparing, as it expects a type fulfilling U extends Comparable<? super U> and while each of String and Integer is capable of fulfilling this constraint in an individual invocation, there is no way to declare a generic return type for getGetterByAttr to allow both type and be still compatible with the declaration of comparing.

替代方案是完整比较器 s的工厂。

An alternative would be a factory for complete Comparators.

public static Comparator<MyObject> getComparator(String s) {
    switch(s) {
        case "attr1": return Comparator.comparing(MyObject::getAttr1);
        case "attr2": return Comparator.comparing(MyObject::getAttr2);
    }
    throw new IllegalArgumentException(s);
}

用作

public void sortListByAttr(List<MyObject> list, String attr) {
    list.sort(getComparator(attr));
}

这样做的好处是它还可以支持类型不是<$的属性c $ c>可比较并需要自定义比较器。此外,原始类型的更有效的比较器(例如使用 comparisonInt )是可能的。

This has the advantage that it also may support properties whose type is not Comparable and requires a custom Comparator. Also, more efficient comparators for primitive types (e.g. using comparingInt) would be possible.

您也可以考虑使用a 地图而不是开关

You may also consider using a Map instead of switch:

private static Map<String,Comparator<MyObject>> COMPARATORS;
static {
    Map<String,Comparator<MyObject>> comparators=new HashMap<>();
    comparators.put("attr1", Comparator.comparing(MyObject::getAttr1));
    comparators.put("attr2", Comparator.comparing(MyObject::getAttr2));
    COMPARATORS = Collections.unmodifiableMap(comparators);
}
public static Comparator<MyObject> getComparator(String s) {
    Comparator<MyObject> comparator = COMPARATORS.get(s);
    if(comparator != null) return comparator;
    throw new IllegalArgumentException(s);
}

只有通过Reflection才能实现更多动态,但这会使代码复杂化,添加考虑到您只需添加一行源代码以添加对上述任一示例中的另一个属性的支持,就会产生很多潜在的错误来源,只有很少的好处。毕竟,定义的属性集在编译时得到修复。

More dynamic is only possible via Reflection, but this would complicate the code, add a lot of potential error source, with only little benefit, considering that you need only to add one line of source code for adding support for another property in either of the examples above. After all, the set of defined properties gets fixed at compile time.

这篇关于根据对象的参数化属性对对象列表进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆