根据指定字段对特定对象的数组进行自定义排序

463 阅读2分钟

排序工具类,可以根据选定字段排序,同时可以处理null值字段排序,如有自定义可自己新增排序方法替换sorted中的排序方式。


import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.comparator.CompareUtil;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 自定义排序
 *
 * @author HY
 */
public class ListSortUtil {

    /**
     * 自定义字段排序
     *
     * @param list
     * @param sortName
     * @param tClass
     * @param desc
     * @param descNull
     * @param <T>
     *
     * @return
     */
    public static <T> List<T> sortListByField(List<T> list, String sortName, Class<T> tClass, boolean desc, boolean descNull) {

        return list.stream()
                .map(convertBeanToMap())
                .sorted(getMapComparator(sortName, desc, descNull))
                .map(convertMapToBean(tClass))
                .collect(Collectors.toList());
    }

    /**
     * 自定义字段排序
     *
     * @param list
     * @param sortName
     * @param desc
     * @param tClass
     * @param <T>
     *
     * @return
     */
    public static <T> List<?> sortListByField(List<T> list, String sortName, boolean desc, Class<T> tClass) {
        return sortListByField(list, sortName, tClass, desc, true);
    }

    /**
     * 是否倒序防范
     *
     * @param sortName
     * @param desc
     * @param descNull
     *
     * @return
     */
    private static Comparator<Map<String, Object>> getMapComparator(String sortName, boolean desc, boolean descNull) {
        if (desc) {
            return (o1, o2) -> getCompareUtil(sortName, descNull, o1, o2);
        }
        return ((Comparator<Map<String, Object>>) (o1, o2) -> getCompareUtil(sortName, descNull, o1, o2)).reversed();
    }


    /**
     * 比较方法
     *
     * @param sortName 排序字段
     * @param descNull null值排序规则
     * @param o1
     * @param o2
     *
     * @return
     */
    private static int getCompareUtil(String sortName, boolean descNull, Map<String, Object> o1, Map<String, Object> o2) {
        return CompareUtil.compare(o1.get(sortName), o2.get(sortName), descNull);
    }


    private static <T> Function<Map<String, Object>, T> convertMapToBean(Class<T> tClass) {
        return map -> BeanUtil.toBean(map, tClass);
    }

    private static <T> Function<T, Map<String, Object>> convertBeanToMap() {
        return BeanUtil::beanToMap;
    }


}

测试方法


import com.java.coco.domian.Person;
import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;

import static com.java.coco.utils.ListSortUtil.sortListByField;
import static org.assertj.core.api.Assertions.assertThat;

/**
 * 自定义排序
 *
 * @author yihur
 */
public class TestSortedStream {


    private List<Person> personList;


    @Before
    public void init_data() {
        personList = Arrays.asList(new Person(null, 18), new Person("Peter", 23), new Person("Anda", 23), new Person("David", 12));
    }


    @Test
    public void test_java_stream_sorted_01() {

        String sortName = "name";
        boolean desc = Boolean.FALSE;
        boolean descNull = Boolean.FALSE;

        List<Person> persons = sortListByField(personList, sortName, Person.class, desc, descNull);

        assertThat(persons.size()).isEqualTo(4);
        assertThat(persons.get(0).getName()).isEqualTo("Peter");
        assertThat(persons.get(1).getName()).isEqualTo("David");
        assertThat(persons.get(2).getName()).isEqualTo("Anda");
        assertThat(persons.get(3).getName()).isNull();
    }


    @Test
    public void test_java_stream_sorted_02() {

        String sortName = "name";
        boolean desc = Boolean.TRUE;
        boolean descNull = Boolean.FALSE;

        List<Person> persons = sortListByField(personList, sortName, Person.class, desc, descNull);
        assertThat(persons.size()).isEqualTo(4);
        assertThat(persons.get(0).getName()).isNull();
        assertThat(persons.get(1).getName()).isEqualTo("Anda");
        assertThat(persons.get(2).getName()).isEqualTo("David");
        assertThat(persons.get(3).getName()).isEqualTo("Peter");
    }


    @Test
    public void test_java_stream_sorted_03() {

        String sortName = "name";
        boolean desc = Boolean.FALSE;
        boolean descNull = Boolean.TRUE;

        List<Person> persons = sortListByField(personList, sortName, Person.class, desc, descNull);

        assertThat(persons.size()).isEqualTo(4);
        assertThat(persons.get(0).getName()).isNull();
        assertThat(persons.get(1).getName()).isEqualTo("Peter");
        assertThat(persons.get(2).getName()).isEqualTo("David");
        assertThat(persons.get(3).getName()).isEqualTo("Anda");
    }


    @Test
    public void test_java_stream_sorted_04() {

        String sortName = "name";
        boolean desc = Boolean.TRUE;
        boolean descNull = Boolean.TRUE;

        List<Person> persons = sortListByField(personList, sortName, Person.class, desc, descNull);
        assertThat(persons.size()).isEqualTo(4);
        assertThat(persons.get(0).getName()).isEqualTo("Anda");
        assertThat(persons.get(1).getName()).isEqualTo("David");
        assertThat(persons.get(2).getName()).isEqualTo("Peter");
        assertThat(persons.get(3).getName()).isNull();
    }

}
@Data
@AllArgsConstructor
public class Person {

    private String name;

    private Integer age;
}