记 HashMap 中按照 Double 类型多位小数 value 排序导致的错误

问题描述

今天写一个实验中使用到了 HashMap,需要对 HashMap 中的 Double 类型 value 进行排序。
先来看一下要排序的数据集:长度为 1000 的 <Integer,Double>HashMap
在这里插入图片描述

解决过程

网上搜到了各种按照 HashMapvalue 进行排序的代码,下面随便贴一个:
(这里我们先使用一组小的虚拟数据进行排序,暂时不使用上面提到的 1000条数据测试)

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;

public class MyIntComparator {

    public static void main(String[] args) {
        Map<Integer, Double> map = new HashMap<Integer, Double>();

        map.put(0, 10.0);
        map.put(1, 20.0);
        map.put(2, 30.0);
        map.put(3, 55.0);
        map.put(4, 60.0);
        map.put(5, 70.2);
        map.put(6, 35.8);

        List<Map.Entry<Integer, Double>> infoIds = new ArrayList<Map.Entry<Integer, Double>>(   map.entrySet());
        //排序前
        for (int i = 0; i < infoIds.size(); i++) {
            String id = infoIds.get(i).toString();
            System.out.println(id);
        }
        //排序
        infoIds.sort(new Comparator<Entry<Integer, Double>>() {
            @Override
            public int compare(Entry<Integer, Double> o1,
                               Entry<Integer, Double> o2) {
                return (int) (o2.getValue() - o1.getValue());
            }
        });
        //排序后
        System.out.println("--------------------------排序后:");
        for (int i = 0; i < infoIds.size(); i++) {
            Entry<Integer, Double> id = infoIds.get(i);
            System.out.println(id);
        }

    }
}

经测试发现,如果对小数点位数较少的数字,如 30.0、40.0 这类数字排序成功:
在这里插入图片描述
如果换成多位小数的数据,上述代码排序失败:

map.put(0, 0.030005979496118867);
map.put(1, 0.005852105829598869);
map.put(2, 0.0077810107361007495);
map.put(3, 0.007566500619860167);
map.put(4, 0.015289105190807142);
map.put(5, 0.006420423776411558);
map.put(6, 0.004273848081981763);

排序结果如下,未能成功排序:
在这里插入图片描述
经过各种搜索,终于发现了一个有效方法,成功对 HashMapDouble 类型的多位小数 value 进行排序:
核心代码:

return (int) ((o2.getValue() - o1.getValue())*10000);

并且可以根据 Double 类型小数点后数字的位数调整上述 10000 中的 0 的个数。
多位小数排序成功:
在这里插入图片描述

附一个小问题:Exception in thread “main” java.lang.IllegalArgumentException: Comparison method violates its general contract!
JDK 兼容问题,一个简单的解决方案:VM参数添加如下设置:
-Djava.util.Arrays.useLegacyMergeSort=true
其他具体解决方案可参考链接:https://blog.csdn.net/xvshu/article/details/70153759

参考链接:http://www.360doc.com/content/08/0818/21/59141_1554099.shtml
在这里插入图片描述

这样会产生一个问题,注意资料中(“D",23.001)、("E”,23.899),这两个资料在强制类型转换后,都是23,没有办法分辨出浮点数的部分,解决方法不难,先确定要取得的小数点位数是多少,像此范例刚好都是小数点三位,那就取到小数点三位,再强制转换成整敷,这样就可以排出正确大小了。程序修改如下:return(int) ((o2.getValue()-o1.getValue())*1000.0);

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悄悄地努力

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值