【问题标题】:JAVA - Sort Array of Json by multiple values while preserving previous sort orderJAVA - 按多个值对 Json 数组进行排序,同时保留先前的排序顺序
【发布时间】:2021-07-25 15:08:19
【问题描述】:

我有这个 json,我希望能够按不同类型的多个字段值对其进行排序,同时保留之前的排序顺序。

  {
    "code": "1603",
    "description": "",
    "score": 10,
    "max": 100,
    "effts": "2021-12-07T00:00:00",
    "expDate": "2021-06-21",
    "charityMaxCount": 1400000,
    "charityUseCount": 938297,
    "title": "",
    "imageUrl": "",
    "status": "INACTIVE"
  },
  {
    "code": "1604",
    "description": "",
    "score": 10,
    "max": 100,
    "effts": "2020-12-07T00:00:00",
    "expDate": "2021-06-21",
    "charityMaxCount": 1400000,
    "charityUseCount": 938297,
    "title": "",
    "imageUrl": "",
    "status": "INACTIVE"
  },
  {
    "code": "1600",
    "description": "",
    "score": 10,
    "max": 100,
    "effts": "2021-12-07T00:00:00",
    "expDate": "2021-06-21",
    "charityMaxCount": 1400000,
    "charityUseCount": 938297,
    "title": "",
    "imageUrl": "",
    "status": "ACTIVE"
  },
  {
    "code": "1606",
    "description": "",
    "score": 10,
    "max": 100,
    "effts": "2022-12-07T00:00:00",
    "expDate": "2021-06-21",
    "charityMaxCount": 1400000,
    "charityUseCount": 938297,
    "title": "",
    "imageUrl": "",
    "status": "ACTIVE"
  },
  {
    "code": "1601",
    "description": "",
    "score": 10,
    "max": 100,
    "effts": "2020-12-07T00:00:00",
    "expDate": "2021-06-21",
    "charityMaxCount": 1400000,
    "charityUseCount": 938297,
    "title": "",
    "imageUrl": "",
    "status": "ACTIVE"
  }
]

我应该决定对其进行排序的字段是通过另一个 json 给出的:

  {
    "id": 1,
    "field": "status",
    "type": "string",
    "sortMode": "ASC"
  },
  {
    "id": 2,
    "field": "expDate",
    "type": "string",
    "sortMode": "ASC"
  }
]

我设法通过将 json 数组转换为 Hashmap<String,Object> 的列表来实现这一点 并编写了一个自定义比较器。问题是当我按 ASC 顺序按 status 排序时,将 ACTIVE 条目放在顶部,我不希望这个顺序弄乱例如,当我选择按 expDate 等其他字段对其进行排序时。

这是我的代码:

    public String sort() throws JsonProcessingException {
        List<TreeMap<String, String>> sortOrder = readSortOrder(sortOrderJson);
        List<HashMap<String, Object>> payLoad = readPayLoad(payloadJson);
        ObjectMapper objectMapper = new ObjectMapper();
        if (sortOrder.size() > 1) {
            for (TreeMap<String, String> map : sortOrder) {
                if (map.get(Constants.SORT_MODE).equals(SortOrder.DSC.toString())) {
                    payLoad.sort(new MapComparator(map.get(Constants.FIELD)).reversed());
                } else {
                    payLoad.sort(new MapComparator(map.get(Constants.FIELD)));
                }
            }
        }
        return objectMapper.writeValueAsString(payLoad);
    }

    public List<HashMap<String, Object>> readPayLoad(String jsonInput) {
        ObjectMapper mapper = new ObjectMapper();
        List<HashMap<String, Object>> jsonList = new ArrayList<>();
        try {
            HashMap[] payLoadDTOS = mapper.readValue(jsonInput, HashMap[].class);
            jsonList = Arrays.asList(payLoadDTOS);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return jsonList;
    }

    public List<TreeMap<String, String>> readSortOrder(String sortOrder) {
        final ObjectMapper objectMapper = new ObjectMapper();
        List<TreeMap<String, String>> jsonList = new ArrayList<>();
        try {
            TreeMap[] sortOrderDTOS = objectMapper.readValue(sortOrder, TreeMap[].class);
            jsonList = Arrays.asList(sortOrderDTOS);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return jsonList;
    }

这是比较器:

public class MapComparator implements Comparator<Map<String, Object>> {

    private final String key;


    public MapComparator(String key) {
        this.key = key;
    }


    @Override
    public int compare(Map<String, Object> one, Map<String, Object> two) {
        Object first = one.get(key);
        Object second = two.get(key);
        if (first instanceof String && second instanceof String) {
            if ((isValidDate((String) first) && isValidDate((String) second))
                    || (isValidDateTime((String) first) && isValidDateTime((String) second))) {
                return DateTimeComparator.getInstance().compare(first, second);
            } else {
                return ((String) first).compareTo((String) second);
            }
        } else if (first instanceof Integer && second instanceof Integer) {
            return ((Integer) first).compareTo((Integer) second);
        }
        return 0;
    }
}

我认为我应该将 ACTIVEINACTIVE 分别放在另外两个集合中并分别排序,但是我可以进行分离的字段可能是动态的,并且可能每次改变。我该如何通过算法处理这个问题?

【问题讨论】:

标签: java json sorting


【解决方案1】:

在相同值条目上保留现有顺序的排序算法称为稳定。在Java中,你可以查询API是否保证给定的排序函数是稳定的,such as Arrays.sort

使用多个键进行排序的典型方式是使用稳定的排序算法对条目进行顺序排序,以键的相反顺序。

例如,如果您想先按名字排序,然后按姓氏排序,则应先按姓氏排序,然后再按名字排序。

您还需要确保您使用的数据结构保留了插入顺序,例如 Set 或 Map 可能不会保留该顺序。

【讨论】:

  • 关于使用列表作为容器,我只是颠倒了顺序,让我免于很多麻烦。谢谢
  • @PouyanKhodabakhsh:不客气!我在计算机科学研究期间了解到这一点,并记住它,因为它经常很有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-08
  • 2013-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多