Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/343.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何对HashMap进行排序';通过比较值(其中每个值都是int[])来设置条目?_Java_Sorting_Dictionary_Java 8_Comparator - Fatal编程技术网

Java 如何对HashMap进行排序';通过比较值(其中每个值都是int[])来设置条目?

Java 如何对HashMap进行排序';通过比较值(其中每个值都是int[])来设置条目?,java,sorting,dictionary,java-8,comparator,Java,Sorting,Dictionary,Java 8,Comparator,我将HashMap定义为HashMap。该值是一个int[],其中正好有2个数字。我想做的是按照这两个数字的总和对HashMap的条目进行排序 这是我的。我正在使用Java8。我只需要在int[]中添加两个int相加的部分,并将其视为一个数字,然后像下面那样排序,但我不确定如何添加该部分 hm.entrySet().stream() .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) 我很确定不能用HashMap

我将HashMap定义为
HashMap
。该值是一个
int[]
,其中正好有2个数字。我想做的是按照这两个数字的总和对HashMap的条目进行排序

这是我的。我正在使用Java8。我只需要在
int[]
中添加两个
int
相加的部分,并将其视为一个数字,然后像下面那样排序,但我不确定如何添加该部分

hm.entrySet().stream()
    .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))

我很确定不能用HashMap创建ordering元素。 我的建议是使用另外两张地图:

Map<Integer,String> tempMap = new TreeMap<Integer,String>();
Map<String,int []> resultMap = new LinkedHashMap<String,int[]>();
Map tempMap=newtreemap();
Map resultMap=newlinkedhashmap();
首先,您需要将hm映射复制到tempMap中,TreeMap中的自然顺序将按升序排列整数键

在tempMap中获得排序结果后,可以复制到resultMap中以获得最终结果

“复制”意味着您迭代旧映射,然后将(键、值)放入新映射

这种方法将花费您两倍的内存,但它将以O(n lg n)的复杂度运行

如果要使用比较器,可以使用以下方法:

hm.entrySet().stream().sorted(Map.Entry.comparingByValue(
    new Comparator<int []>() {
    public int compare(int [] a,int [] b) {
        int sumA = a[0] + a[1];
        int sumB = b[0] + b[1];
        return sumA - sumB;
    }
}));
hm.entrySet().stream().sorted(Map.Entry.comparingByValue(
新比较器(){
公共整数比较(整数[]a,整数[]b){
int sumA=a[0]+a[1];
int sumB=b[0]+b[1];
返回sumA-sumB;
}
}));

这个答案实际上受到了Hesham Attia的另一个答案的启发,可以作为这个问题的替代解决方案

不过,我也借此机会讨论了
int
数据类型溢出的潜在问题(请参阅下文)

此解决方案使用接口
Comparator.comparingLong()
键提取器
,而不是接口
映射.Entry.comparingByValue()
比较器

(如果我们不够小心,两者都可能出现数据溢出的问题——请参见下面的测试2和测试3。)

这里是一个完整的测试程序,它演示了中间测试失败的2和3。排序的正确答案应该是

e、b、c、a、d
(如测试4所示)

通过简单的减法实现比较器的危险

上述测试程序(测试2)中显示了此问题,但也已解决 在Oracle/Sun对象排序教程中警告

最后一点注意:您可能会尝试替换最终返回 比较表中的语句更简单:

返回e1.number()-e2.number()

除非你完全同意,否则不要这样做 当然没有人会有一个负的员工号码!这个把戏很管用 通常不起作用,因为有符号整数类型不够大 表示两个任意有符号整数的差。如果我是 一个大的正整数,而j是一个大的负整数,i-j将 溢出并将返回一个负整数。结果比较器 违反了我们一直在谈论的四个技术限制之一 (及物性)并产生可怕、微妙的bug。这不是一个好主意 纯粹的理论关注;人们会被它烧伤


以下是使用Java 8 Comparator lambdas的解决方案:

map.entrySet().stream()
              .sorted(Map.Entry.comparingByValue(
                      (v1, v2) -> v2[0] + v2[1] - v1[0] - v1[1]));

请注意,此解决方案存在溢出/下溢的风险,有关更好的解决方案,请参阅。我们的想法是使用
comparingLong
方法。

更一般的解决方案,使用合适的比较器(不受可能的溢出问题的影响),它将适用于任何长度的数组:

1) 由于无法对不保留键顺序的
HashMap
进行排序,我们需要创建新的map-
LinkedHashMap

    Map<String, int[]> result = new LinkedHashMap<>();

UPD:Dear@Holger建议使用
Comparator.comparingit(o->Arrays.stream(o.sum())
,它看起来更紧凑,但功能相同。就我个人而言,我的版本看起来更容易理解,但霍尔格的版本更容易理解。

最简单也是最好的方法是不使用映射。条目比较方法,因为您不是按键或值进行比较,而是按派生值进行比较:

map.entrySet().stream()
    .sorted(Comparator.comparing(e -> 0 - e.getValue()[0] - e.getValue[1]))
    .forEach(<whatever>);
map.entrySet().stream()
.sorted(Comparator.comparing(e->0-e.getValue()[0]-e.getValue[1]))
.forEach();

负值创建代码建议的相反顺序。

要做到这一点,您必须编写自己的比较器。我是比较器新手,但我是否应该向它传递一个函数,将两个int相加到int[]中?
HashMap
不保留任何顺序。如果您正试图这样做,那么您将需要一个不同的数据结构。或者你只是想按这个顺序迭代条目?“Sort a
HashMap
在术语上已经是一个矛盾。编辑它是为了澄清映射条目的排序。+1表示“你不能用HashMap创建排序元素”,但我必须承认,我看不出有任何理由不将其保留为TreeMap(不需要“resultMap”)我使用resultMap的原因是为了保留原始结构:HashMap、字符串作为键、int[]作为值。我使用PrintWriter写入文件进行检查,但它会打印内存地址,我想打印int[]?这与此无关,但您可以使用Array.toString正确打印数组<代码>map.entrySet().stream().sorted(map.Entry.comparingByValue((v1,v2)->v2[0]+v2[1]-v1[0]-v1[1]).forEach(e->{System.out.println(“Key:+e.getKey()+”Value:“+Arrays.toString(e.getValue());”)@Hesham--Hi我喜欢这个答案。但我认为通过简单的减法实现比较器存在危险。我在下面的回答中提供了我的解释。同意!感谢您指出这一点,我将添加一个免责声明。这可能是简单的印刷错误。但你们是否同意,这不会影响结果,也不是一般的错误?而且,
a[0]+a[1]
不是c
map.entrySet().stream()
              .sorted(Map.Entry.comparingByValue(
                      (v1, v2) -> v2[0] + v2[1] - v1[0] - v1[1]));
    Map<String, int[]> result = new LinkedHashMap<>();
    map.entrySet().stream()
            .sorted(Map.Entry.comparingByValue(
                            (o1, o2) -> Integer.compare(Arrays.stream(o1).sum(), Arrays.stream(o2).sum()))
            )
    .forEach(se -> result.put(se.getKey(), se.getValue()));
map.entrySet().stream()
    .sorted(Comparator.comparing(e -> 0 - e.getValue()[0] - e.getValue[1]))
    .forEach(<whatever>);