首页 > 解决方案 > 使用 Java 8 为类中任意数量的字段构建比较器逻辑

问题描述

我正在尝试使用Comparator.comparing()Java 8 中引入的自定义比较逻辑。

要求是:如果在 Person 类中引入了新字段,代码应该可以工作。它应该将新领域纳入比较逻辑。

这意味着比较逻辑应该是这样的:id --> name --> new field1 --> new field2

请参阅下面的伪代码:

package test;

import java.lang.reflect.Field;
import java.util.Comparator;

public class Test6 {
    
    public static void main (String args []) {
        Field[] declaredFields = Person.class.getDeclaredFields();
        
        Comparator<Person> comparator = Comparator.comparing((Person x)-> x.getId());
        for (int i=1; i<declaredFields.length ; i++) {
            comparator = comparator.thenComparing(field[i]);  // what code should I place over here, to make it work for field obtained above.
        }

   List<Person> persons = new ArrayList<>();
     persons.stream().sorted(comparator).collect(Collectors.toList());
    }


}

class Person{
    int id ;
    String name;
    // if we add new field , then this field should also be included in comparison logic

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    
    
}

标签: javajava-8comparator

解决方案


在 Apache Commons BeanUtils 中有一个BeanComparator基于反射的有用比较器。结合 ReverseComparator 可以编写一个动态比较器。

<dependency>
   <groupId>commons-beanutils</groupId>
   <artifactId>commons-beanutils</artifactId>
   <version>1.9.3</version>
</dependency>

简单的例子:

public static <T> Comparator<T> beanComparator(String fieldName, boolean asc) {
    Comparator<T> propertyComparator;
    if (asc) {
        propertyComparator = new BeanComparator<>(fieldName);
    } else {
        propertyComparator = new ReverseComparator(new BeanComparator<>(fieldName));
    }
    return propertyComparator;
}

推荐阅读