在Java 8中以通用方法对集合进行排序 - java

以下方法执行排序。

public List<Comparator<Entity>> sort(Map<String, String> map) {
    List<Comparator<Entity>> list = new ArrayList<Comparator<Entity>>();

    for (Map.Entry<String, String> entry : map.entrySet()) {
        boolean sortOrder = entry.getValue().equalsIgnoreCase("asc");

        switch (entry.getKey()) {
            case "id":
                list.add(sortOrder ? Comparator.comparing(Entity::getId) : Comparator.comparing(Entity::getId, Comparator.reverseOrder()));
                break;
            case "size":
                list.add(sortOrder ? Comparator.comparing(Entity::getSize) : Comparator.comparing(Entity::getSize, Comparator.reverseOrder()));
                //break;
        }
    }

    return list;
}

由上述方法返回的列表以下列方式使用。

// map is initialized somewhere based on client's interactions with sorting.
// Based on client's interactions, map may be empty or it may contain one or more ordering fields.

if (MapUtils.isNotEmpty(map)) {  // map = new LinkedHashMap<String, String>();

    List<Comparator<Entity>> comparators = sort(map);
    Comparator<Entity> comparator = comparators.remove(0);

    for (Comparator<Entity> c : comparators) {
        comparator = comparator.thenComparing(c);
    }

    list = list.stream().sorted(comparator).collect(Collectors.toList());
} else {
    // This is the default ordering.
    list = list.stream().sorted(Comparator.comparing(Entity::getId).reversed()).collect(Collectors.toList());
}

Entity包含两个名为id且类型为IntegersizeBigDecimallist类型的字段。

由于还有其他几个具有相同字段和相同数据类型的类,因此我希望此方法是通用的,因此只需像这样定义一次,

public <T extends Object> List<Comparator<T>> sort(Map<String, String> map, Class<T> clazz) {
    List<Comparator<T>> list = new ArrayList<Comparator<T>>();

    // Sorting logic.

    return list;
}

但是这样做的话,像List<Entity>这样的表达式将不会被编译,因为通用类型参数T::getId的结果为T

有没有一种方法可以在不知道实际类类型的情况下进行代码排序,从而可以防止在需要时在任何地方重复使用此方法?

参考方案

一种简单的方法(不必依靠反射魔术)是为具有与Entity相同的数据类型的相同字段的所有类型引入一个公共接口。

考虑以下IdSize接口和以下Entity接口。

interface IdSize {
    Integer getId();
    BigDecimal getSize();
}

class Entity implements IdSize {

    private Integer id;
    private BigDecimal size;
    @Override
    public Integer getId() {
        return id;
    }
    @Override
    public BigDecimal getSize() {
        return size;
    }

}

然后,您可以使方法通用,如下所示:

public <T extends IdSize> List<Comparator<T>> sort(Map<String, String> map) {
    List<Comparator<T>> list = new ArrayList<Comparator<T>>();
    for (Map.Entry<String, String> entry : map.entrySet()) {
        boolean sortOrder = entry.getValue().equalsIgnoreCase("asc");
        Comparator<T> comparator = null;
        switch (entry.getKey()) {
            case "id":
                comparator = Comparator.comparing(IdSize::getId);
                break;
            case "size":
                comparator = Comparator.comparing(IdSize::getSize);
                break;
            default: // do something here, throw an exception?
        }
        list.add(sortOrder ? comparator : comparator.reversed());
    }
    return list;
}

(我对switch-case语句进行了一些重构,以删除重复的代码。)另外,您可能想添加一个默认子句。

Diamond运算符(<>)在Java 1.7中不起作用 - java

编译jsp文件时出现以下错误: 低于1.7的源级别不允许使用''运算符我正在使用jdk 1.7.x和eclipse Kepler另外我已经在Eclipse的项目首选项中设置了1.7 as compliance level,但是代码仍然无法正常工作我应该添加其他配置吗? 参考方案 检查Eclipse中的以下区域:Right Click Project >…

在Java Swing中输入JButton的键焦点? - java

如何在Java Swing中使JButton的Enter键成为焦点?我已经这样做了btn_Login.registerKeyboardAction(new ActionListener() { public void actionPerformed(ActionEvent e) { System.out.println("enter key pre…

无法从ArrayList <String>转换为List <Comparable> - java

当我写下面的代码时,编译器说 无法从ArrayList<String>转换为List<Comparable>private List<Comparable> get(){ return new ArrayList<String>(); } 但是当我用通配符编写返回类型时,代码会编译。private List&l…

合并List <T>和List <Optional <T >> - java

鉴于: List<Integer> integers = new ArrayList<>(Arrays.asList( 10, 12 )); List<Optional<Integer>> optionalIntegers = Arrays.asList( Optional.of(5), Optional.em…

实例化类型<?>的泛型类 - java

我正在为SCJP / OCPJP学习,并且遇到了一个对我来说很奇怪的示例问题。该示例代码实例化了两个通用集合:List<?> list = new ArrayList<?>(); List<? extends Object> list2 = new ArrayList<? extends Object>(); …