在Java 8中对通用方法中的集合进行排序 [英] Sorting a collection in a generic method in Java 8

查看:116
本文介绍了在Java 8中对通用方法中的集合进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



  public List< Comparator< Entity>> sort(Map< String,String> map){
List< Comparator< Entity>> list = new ArrayList< Comparator< Entity>>(); (Map.Entry< String,String> entry:map.entrySet()){
boolean sortOrder = entry.getValue()。equalsIgnoreCase(asc);



switch(entry.getKey()){
caseid:
list.add(sortOrder?Comparator.comparing(Entity :: getId):Comparator.comparing Entity :: getId,Comparator.reverseOrder()));
休息;
casesize:
list.add(sortOrder?Comparator.comparing(Entity :: getSize):Comparator.comparing(Entity :: getSize,Comparator.reverseOrder()));
// break;
}
}

返回列表;
}

上述方法返回的列表的使用方式如下。 / p>

  // map是根据客户端与排序的交互进行初始化的。 
//基于客户端的交互,地图可能是空的,或者它可能包含一个或多个排序字段。

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

List< Comparator< Entity>>比较器=排序(地图);
比较器< Entity> comparator = comparators.remove(0); (比较器<实体> c:比较器)

{
比较器= comparator.thenComparing(c);


list = list.stream()。sorted(comparator).collect(Collectors.toList());
} else {
//这是默认排序。
list = list.stream()。sorted(Comparator.comparing(Entity :: getId).reversed())。collect(Collectors.toList());

code

$ b $实体
包含两个类型为 Integer 大小的类型为 id code> BigDecimal 和 list 是一种 List< Entity>


由于有几个其他类具有相同数据类型的相同字段,我希望这个方法是通用的,因此它必须像这样定义一次, / p>

  public< T extends Object>列表与LT;比较< T>> (Map< String,String> map,Class< T> clazz){
List< Comparator< T>> list = new ArrayList< Comparator< T>>();

//排序逻辑。

返回列表;
}

但是这样做,像 T :: getId因为泛型类型参数 T 的计算结果为 Object / p>

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

解决方案

一种简单的方法,无需依赖反射魔术,就可以为所有具有相同数据类型的字段引入一个通用接口, 实体



考虑以下 IdSize 实体

 接口IdSize {
Integer getId( );
BigDecimal getSize();
}

类实体实现IdSize {

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

}

然后你可以使你的方法成为通用的像这样:

  public< T extends IdSize>列表与LT;比较< T>> sort(Map< String,String> map){
List< Comparator< T>> list = new ArrayList< Comparator< T>>(); (Map.Entry< String,String> entry:map.entrySet()){
boolean sortOrder = entry.getValue()。equalsIgnoreCase(asc);
比较器< T> comparator = null;
switch(entry.getKey()){
caseid:
comparator = Comparator.comparing(IdSize :: getId);
休息;
casesize:
comparator = Comparator.comparing(IdSize :: getSize);
休息;
default://在这里做些什么,抛出异常?
}
list.add(sortOrder?comparator:comparator.reversed());
}
返回列表;
}

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


The following method performs ordering.

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

The list being returned by the above method is used in the following way.

// 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 contains two fields named id of type Integer and size of type BigDecimal and list is a type of List<Entity>.

Since there are several other classes having the same fields with the same datatypes, I want this method to be generic so that it has to be defined only once like so,

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

But doing so, expressions like T::getId will not compile as obvious, since the generic type parameter T evaluates to Object.

Is there a way to code sorting without knowing the actual class type so that this method can be prevented from being repeated everywhere, when it is needed?

解决方案

A simple way, without having to rely on reflection magic, is to introduce a common interface for all the types having the same fields with the same datatypes as Entity.

Consider the following IdSize interface with the following 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;
    }

}

Then you can make your method generic like this:

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

(I refactored a little the switch-case statement to remove the duplicated code.). Also, you might want to add a default clause.

这篇关于在Java 8中对通用方法中的集合进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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