【问题标题】:Sort java object based on a key基于键对java对象进行排序
【发布时间】:2024-01-21 07:05:01
【问题描述】:

我有一个数据列表,我需要以下面的方式有效地对job_status 下的pre_release 进行排序,仅适用于具有run 的对象:1

"FAILED", "WARNING", "SUCCESS"

我正在尝试使用冒泡排序,但需要帮助

//compareData contains list of object which needs to be sorted
List<HashMap<String, Object>> compareData = new ArrayList<HashMap<String, Object>>();

HashMap<String, Object> tempObj = new HashMap<String, Object>();
for (int i=0; i<compareData.size(); i++) {
    for (int j=1; i<(compareData.size() - 1); j++) {

        if (Integer.parseInt(compareData.get(j-1).get(JOB_STATUS_CODE).toString()) > Integer.parseInt(compareData.get(j).get(JOB_STATUS_CODE).toString())) {
            tempObj = compareData.get(j-1);
            //compareData.get(j-1) = compareData.get(j);

        }
    }
}

比较数据

[{
    "pre_release": [{
        "message": "The environment GYAN-WIN2008-64-SP2-DC-1 used by this connection is inactive.",
        "start_time": "2015-05-27T22:45:25.000-07:00",
        "run": "1",
        "job_status": "FAILED",
        "job_status_code": "3"
    }, {
        "message": "The environment GYAN-WIN2008-64-SP2-DC-1 used by this connection is inactive.",
        "start_time": "2015-05-27T22:00:25.000-07:00",
        "run": "2",
        "job_status": "FAILED",
        "job_status_code": "3"
    }, {
        "message": "The environment GYAN-WIN2008-64-SP2-DC-1 used by this connection is inactive.",
        "start_time": "2015-05-27T21:15:25.000-07:00",
        "run": "3",
        "job_status": "FAILED",
        "job_status_code": "3"
    }],
    "task_name": "DB to DB xxx.yyy.42.62_2",
    "task_id": "000ABC0G000000000007",
    "production": {
        "message": "The environment Redhat Linux used by this connection is inactive.",
        "start_time": "2015-05-21T05:50:05.000-07:00",
        "job_status": "FAILED",
        "job_status_code": "3"
    }
} {
    "pre_release": [{
        "message": "The environment Redhat Linux used by this connection is inactive.",
        "start_time": "2015-05-21T05:50:05.000-07:00",
        "run": "1",
        "job_status": "FAILED",
        "job_status_code": "3"
    }, {
        "message": "The environment Redhat Linux used by this connection is inactive.",
        "start_time": "2015-05-21T05:45:05.000-07:00",
        "run": "2",
        "job_status": "FAILED",
        "job_status_code": "3"
    }, {
        "message": "The environment Redhat Linux used by this connection is inactive.",
        "start_time": "2015-05-21T05:40:05.000-07:00",
        "run": "3",
        "job_status": "FAILED",
        "job_status_code": "3"
    }],
    "task_name": "IPS_WS_Test",
    "task_id": "000ABC0K000000000096",
    "production": {
        "message": null,
        "start_time": "2015-02-02T13:05:00.000-08:00",
        "job_status": "SUCCESS",
        "job_status_code": "1"
    }
}, {
    "pre_release": [{
        "message": null,
        "start_time": "2015-02-02T13:05:00.000-08:00",
        "run": "1",
        "job_status": "SUCCESS",
        "job_status_code": "1"
    }, {
        "message": null,
        "start_time": "2015-02-02T13:00:00.000-08:00",
        "run": "2",
        "job_status": "SUCCESS",
        "job_status_code": "1"
    }, {
        "message": null,
        "start_time": "2015-02-02T12:55:00.000-08:00",
        "run": "3",
        "job_status": "SUCCESS",
        "job_status_code": "1"
    }],
    "task_name": "Logan josh mct win",
    "task_id": "000ABC0Z00000000009V",
    "production": {
        "message": "No errors encountered.",
        "start_time": "2015-05-19T13:31:28.000-07:00",
        "job_status": "SUCCESS",
        "job_status_code": "1"
    }
}, {
    "pre_release": [{
        "message": null,
        "start_time": "2015-05-14T07:27:10.000-07:00",
        "run": "1",
        "job_status": "WARNINGS",
        "job_status_code": "2"
    }, {
        "message": "Target field [MD_COntact__c] does not exist in the object [onlytesting__c].",
        "start_time": "2015-05-14T07:25:25.000-07:00",
        "run": "2",
        "job_status": "FAILED",
        "job_status_code": "3"
    }, {
        "message": "Target field [MD_COntact__c] does not exist in the object [onlytesting__c].",
        "start_time": "2015-05-14T07:24:55.000-07:00",
        "run": "3",
        "job_status": "FAILED",
        "job_status_code": "3"
    }],
    "task_name": "Lambba",
    "task_id": "000ABCI0000000002XP",
    "production": {
        "message": null,
        "start_time": "2015-05-14T07:27:10.000-07:00",
        "job_status": "WARNINGS",
        "job_status_code": "2"
    }
}, {
    "pre_release": [{
        "message": "No errors encountered.",
        "start_time": "2015-05-19T13:31:28.000-07:00",
        "run": "1",
        "job_status": "SUCCESS",
        "job_status_code": "1"
    }, {
        "message": "No errors encountered.",
        "start_time": "2015-05-19T13:12:15.000-07:00",
        "run": "2",
        "job_status": "SUCCESS",
        "job_status_code": "1"
    }, {
        "message": "No errors encountered.",
        "start_time": "2015-05-19T12:51:50.000-07:00",
        "run": "3",
        "job_status": "SUCCESS",
        "job_status_code": "1"
    }],
    "task_name": "chahamedidata_baja2",
    "task_id": "000ABC0I000000000301",
    "production": {
        "message": "[ERROR] com.baja.api.bajaServiceQueryOperationTimeIntervalFaultFaultFaultMessage: Query is limited to 1 request every 250 milliseconds (there have been 64.2 milliseconds since the last request)",
        "start_time": "2015-05-19T13:20:05.000-07:00",
        "job_status": "SUCCESS",
        "job_status_code": "1"
    }
}]

更新

所以我做了类似下面的事情,但我得到了Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!

Collections.sort(compareData, new Comparator<HashMap<String, Object>>() {
    @SuppressWarnings("unchecked")
    @Override
    public int compare(HashMap<String, Object> o1, HashMap<String, Object> o2) {
        // TODO Auto-generated method stub
        int i = 0;
        ArrayList<?> firstArray = (ArrayList<?>) o1.get(PRE_RELEASE);
        ArrayList<?> secondArray = (ArrayList<?>) o2.get(PRE_RELEASE);
        do {
            //System.out.println (((HashMap<String,Object>) firstArray.get(i)).get("run"));
            if (((HashMap<String,Object>) firstArray.get(i)).get("run").equals("1")) {
                if (((HashMap<String,Object>) firstArray.get(i)).get(JOB_STATUS).equals(((HashMap<String,Object>) secondArray.get(i)).get(JOB_STATUS))) {
                    return 0;
                } else {
                    if (((HashMap<String,Object>) firstArray.get(i)).get(JOB_STATUS).equals("FAILED")) 
                        return -1;
                    else if (((HashMap<String,Object>) firstArray.get(i)).get(JOB_STATUS).equals("WARNING")) {
                        return ((HashMap<String,Object>) firstArray.get(i)).get(JOB_STATUS).equals("FAILED") ? 1 : -1;
                    }
                    else {
                        return 1;
                    }
                }
            }
            i++;
        } while (i < firstArray.size());
        return 0;
    }
});

【问题讨论】:

  • 为什么要重写排序算法? Collections.sortComparator 实例有任何问题吗?
  • 唯一的原因。家庭作业。
  • @fix 查看看似不太可能的样本数据(或非常彻底的练习......)
  • @dotvav:我使用了Collections.sortComparator,但我得到了Comparison method violates its general contract! 异常。请查看我更新的问题。

标签: java sorting quicksort bubble-sort


【解决方案1】:

比较器需要尊重比较的传递性。意思是如果a=bb=c 然后a=c,与&gt;&lt; 相同。在太多情况下,您的实现只是简单地返回0。我建议您研究以下方法:

    List<HashMap<String, Object>> compareData = new ArrayList<>();
    Collections.sort(compareData, new Comparator<HashMap<String, Object>>() {
        @SuppressWarnings("unchecked")
        @Override
        public int compare(HashMap<String, Object> o1, HashMap<String, Object> o2) {
            ArrayList<?> firstArray = (ArrayList<?>) o1.get(PRE_RELEASE);
            ArrayList<?> secondArray = (ArrayList<?>) o2.get(PRE_RELEASE);

            Object firstRun1 = null;
            for (Object firstRun : firstArray) {
                if (((HashMap<String,Object>) firstRun).get("run").equals("1")) {
                    firstRun1 = firstRun;
                    break;
                }
            }

            Object secondRun1 = null;
            for (Object secondRun : secondArray) {
                if (((HashMap<String,Object>) secondRun).get("run").equals("1")) {
                    secondRun1 = secondRun;
                    break;
                }
            }

            if (firstRun1 == secondRun1) {
                return 0;
            }
            else if (firstRun1 == null) {
                return -1;
            }
            else if (secondRun1 == null) {
                return 1;
            }
            else {
                String firstStatus = (String) ((HashMap<String,Object>) firstRun1).get(JOB_STATUS);
                String secondStatus = (String) ((HashMap<String,Object>) secondRun1).get(JOB_STATUS);

                return toNum(firstStatus).compareTo(toNum(secondStatus));
            }
        }
    });

toNum 方法:

Integer toNum(String status) {
    return "FAILED".equals(status) ? 0 : ("WARNING".equals(status) ? 1 : 2);
}

很抱歉我无法测试它,因为我缺少你的一些代码。

现在还有一个建议:这段代码中有太多未经检查的转换和强制转换。我建议您直接向 JSONObject 工作,在解析 Json 时框架可能会返回给您,或者您将业务对象映射到真正的 POJO 而不是 Objects 的映射和列表。

【讨论】:

  • 感谢您的解决方案,但我不理解 toNum 的 lambda 部分
  • 我更新了答案并删除了 lambda 表达式
【解决方案2】:

这个:

for (int j=1; i<(compareData.size() - 1); j++)

应该是

for (int j=1; j<(compareData.size() - 1); j++)

注意 (i -> j)

【讨论】:

    【解决方案3】:

    您不只是对集合进行排序。您首先对其进行过滤(run=1),然后对剩下的内容进行排序。

    让我们释放一些 Java8。我假设您的 pre_release 集合已排序,因为在您的示例中,数据 run=1 始终是第一个

    List<MyItems> list = new LinkedList<>();
    //Populate your list somehow.
    list.stream()
    .sorted((x1, x2) -> {
      String status1 = x1.pre_release[0].job_status;
      String status2 = x2.pre_release[0].job_status;
      if (x1.equals(x2)) return 0;
      else {
        if (x1.equals("FAILED")) {
          return -1;
        }
        else if (x1.equals("WARNING")) {
          return x2.equals("FAILED") ? 1 : -1;
        }
        else {
          return 1;
        }
      }
    })
    .collect(Collectors.toList());
    

    如果不是这样,那么你需要更改分配status1和status2的代码来搜索run = 1;

    【讨论】:

    • 感谢您的解决方案。我正在使用 java 7。
    • @Ricky 然后只需用 Collections.sort(new Comparator {...}) 替换“.stream().sorted()”调用,并用完全相同的代码填充代码逻辑。
    • 我按照你的建议更新了我的代码,但我收到了Comparison method violates its general contract!。请帮忙