java - 使用 Java 8 中的泛型方法对集合进行排序

标签 java sorting generics java-8

以下方法执行排序。

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 的字段类型 Integersize类型 BigDecimallistList<Entity> 的一种类型.

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

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;
}

但是这样做的话,像 T::getId 这样的表达式不会编译得那么明显,因为泛型类型参数 T计算结果为Object .

有没有一种方法可以在不知道实际类类型的情况下编写排序代码,以便在需要时可以防止该方法在任何地方重复?

最佳答案

一种无需依赖反射魔法的简单方法是为所有具有与 Entity 相同字段和相同数据类型的类型引入一个通用接口(interface)。

考虑以下 IdSize 接口(interface)和以下 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 语句以删除重复的代码。)。另外,您可能想要添加默认子句。

关于java - 使用 Java 8 中的泛型方法对集合进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33084560/

相关文章:

python - 以相同的顺序一次洗牌两个列表

ios - Swift Generic Class无法分配给子类

java - "Autowire"部署spring模块化应用到tomcat后失败

java - 调试特定于总(最大)深度方法的自定义二叉树

java - Apache Wink 连接到 https 资源

c - 在冒泡排序中得到错误的输出

javascript - 拖放并计算宽度

java - 使用泛型时如何解决这个未经检查的转换错误?

generics - Kotlin中的Nothing或Any和有什么区别

java - BindException/在负载下使用 HttpClient 时打开的文件过多