基于值的排序列表< map< string,object>>

ux6nzvsh  于 2021-07-03  发布在  Java
关注(0)|答案(2)|浏览(433)

基本上我有一个 List<Map<String,Object>> ,我想根据Map中某个键的值对其进行排序。
问题是我不知道。。。这个Map可以包含字符串,整数,双精度,浮点等。。。。我想把它分类:
到目前为止

List<Map<String,Object>> data = getResults();
Collections.sort(data, (o1, o2) -> (String.valueOf(o2.get("Field1")))
              .compareTo((String.valueOf(o1.get("Field1")))));

这不是一个好主意,因为数字没有正确排序。。。。我怎么处理?

goucqfw6

goucqfw61#

首先,您必须定义所需的顺序,特别是字符串值的位置,或者它们都是文本形式的数字?
然后实现一个更复杂的comparator方法,从最高优先级到最低优先级遍历比较标准。
未经测试:

List<Map<String, Object>> list = new ArrayList<>();
    Collections.sort(list, (map1, map2) -> {
      Object v1 = map1.get("Field1");
      Object v2 = map2.get("Field1");

      // --------------------------------------------
      // handle null
      // --------------------------------------------
      if(v1 == null && v2 == null) {
        return 0;
      }

      if(v1 == null && v2 != null) {
        return -1 /* null value before non-null value */;
      }

      if(v1 != null && v2 == null) {
        return 1 /* non-null value after null value */;
      }

      // --------------------------------------------
      // handle String
      // --------------------------------------------
      boolean v1IsString = v1 instanceof String;
      boolean v2IsString = v2 instanceof String;
      if(v1IsString && v2IsString) {
        return ((String) v1).compareToIgnoreCase((String) v2);
      }

      if(v1IsString && !v2IsString) {
        return -1 /* string value before non-string values */;
      }

      if(!v1IsString && v2IsString) {
        return 1 /* non-string value after string value */;
      }

      // --------------------------------------------
      // handle LocalDate
      // --------------------------------------------
      // ....

      // --------------------------------------------
      // handle Instant
      // --------------------------------------------
      // ....

      // --------------------------------------------
      // handle BigDecimal and BigInteger
      // --------------------------------------------
      // ....

      // --------------------------------------------
      // handle Number
      // --------------------------------------------
      boolean v1IsNumber = v1 instanceof Number;
      boolean v2IsNumber = v2 instanceof Number;
      if(v1IsNumber && v2IsNumber) {
        double d1 = ((Number) v1).doubleValue();
        double d2 = ((Number) v2).doubleValue();
        return (int) Math.signum(d1 - d2);
      }

      if(v1IsNumber && !v2IsNumber) {
        return -1 /* number value before non-number values */;
      }

      if(!v1IsNumber && v2IsNumber) {
        return 1 /* non-number value after number value */;
      }

      // etc.

      // --------------------------------------------
      // finally, treat all unhandled value types as equal
      // --------------------------------------------
      return 0;
    });
hfyxw5xn

hfyxw5xn2#

您可以通过比较双精度值来概括比较数字,因为它们是最大的。如果两个对象无法转换为数字,并且无法从这些对象中解析双精度值,则比较它们的字符串值:

List<Map<String, Object>> data = Arrays.asList(
        Map.of("Field1", 21.2d),  // Double
        Map.of("Field1", "qqq"),  // String
        Map.of("Field1", "22.5"), // String
        Map.of("Field1", 2),      // Integer
        Map.of("Field1", 3L),     // Long
        Map.of("Field1", 23.1f)); // Float
data.sort(Comparator.comparingDouble((Map<String, Object> map) -> {
    Object object = map.get("Field1");
    if (object instanceof Number) {
        return ((Number) object).doubleValue();
    } else {
        try {
            return Double.parseDouble(String.valueOf(object));
        } catch (NumberFormatException e) {
            return Double.NaN;
        }
    }
}).thenComparing(map -> String.valueOf(map.get("Field1"))));
data.forEach(System.out::println);
// {Field1=2}
// {Field1=3}
// {Field1=21.2}
// {Field1=22.5}
// {Field1=23.1}
// {Field1=qqq}

另请参见:按列标题对二维列表排序

相关问题