当前位置: 首页 > 知识库问答 >
问题:

JavaArrays.sort[副本]

慎风畔
2023-03-14

正如我所想的那样,我一直在解决一个算法问题并找到了解决方案。但没想到我遇到了一个奇怪的问题。

让我们假设我在英特尔第11代处理器java 8/17上有以下代码(两者都有):

import java.util.Arrays;
import java.util.concurrent.ThreadLocalRandom;

public class DistanceYandex{
    static class Elem implements Comparable<Elem>{
        int value;
        int index;
        long dist;
        public Elem(int value, int index){
            this.value = value;
            this.index = index;
        }

        @Override
        public int compareTo(Elem o){
            return Integer.compare(value, o.value);
        }
    }
    public static void main(String[] args){
        int n = 300_000;
        int k = 3_000;
        Elem[] elems = new Elem[n];
        for(int i = 0; i < n; i++){
            elems[i] = new Elem(ThreadLocalRandom.current().nextInt(), i);
        }
        solve(n, k, elems);
    }
    private static void solve(int n, int k, Elem[] elems){
        Arrays.sort(elems); // interesting line
        long time = System.nanoTime();

        for(int i = 0; i < n; i++){
            elems[i].dist = findDistForIth(elems, i, k);
        }
//        i omit output, because it's irrelevant
//        Arrays.sort(elems, Comparator.comparingInt(elem -> elem.index));
//        System.out.print(elems[0].dist);
//        for(int i = 1; i < n; i++){
//            System.out.print(" " + elems[i].dist);
//        }
        System.out.println((System.nanoTime() - time)/1_000_000_000.0);
    }

    private static long findDistForIth(Elem[] elems, int i, int k){
        int midElem = elems[i].value;
        int left = i - 1;
        int right = i + 1;
        long dist = 0;
        for(int j = 0; j < k; j++){
            if(left < 0){
                dist += elems[right++].value - midElem;
            }else if(right >= elems.length){
                dist += midElem - elems[left--].value;
            }else{
                int leftAdd = midElem - elems[left].value;
                int rightAdd = elems[right].value - midElem;
                if(leftAdd < rightAdd){
                    dist+=leftAdd;
                    left--;
                }else{
                    dist+=rightAdd;
                    right++;
                }
            }
        }
        return dist;
    }
}

把你的眼睛指向解决函数。

在这里我们有一个简单的解决方案,调用函数 findDistForIth n 次并测量所需的时间(我不使用 JMH,因为我的问题的测试html" target="_blank">系统使用简单的一次性时间测量)。在捕获开始时间之前,它使用内置的 Arrays.sort 函数按自然顺序对数组进行排序。

正如您所注意到的,测量的时间不包括数组排序的时间。此外,函数findDisdiForIth的行为并不取决于输入数组是否排序(它主要去第三个其他分支)。但是如果我用Arrays.sort注释掉一行,我会得到更快的执行速度:而不是大约7.3秒,大约需要1.6秒。快了4倍多!

我不明白这是怎么回事。

我想也许是gc在这里搞砸了,我试图将我给jvm的内存增加到2gb(-Xmx2048M -Xms2048M)。没帮助。

我试图将显式比较器作为第二个参数传递给< code>Arrays.sort

我启动了分析器(Intellij Profiler)

但这并没有给我多少信息。。。

我尝试将它直接构建到.jar并通过javacmd启动(在通过intellij启动之前)。这也无济于事。

有人知道怎么回事吗?

这个问题也在在线编译器中重复出现:https://onlinegdb.com/MPyNIknB8T

共有1个答案

郭建华
2023-03-14

可能需要使用红黑树排序算法对数据进行排序,该算法在SortedSet数组中实现。排序使用mergesort排序算法,该算法适用于少量数据

 类似资料:
  • 我对这个(可能是)简单的铸造示例有一个棘手的问题。你能帮帮我吗? 但更尴尬的是,我不知道为什么其他两种说法都没问题。 我看不出OtherIf和ChildIf之间有任何联系。那么,在案例1中,当这两个接口之间没有“扩展”时,如何将OtherIf强制转换为ChildIf呢?

  • 我需要一些帮助来理解我的程序哪里出错了,我有一个非常简单的程序来学习多线程,但是每次我运行下面的代码时,它给我一个IllegalStateMonitorException。我不知道是什么原因造成的,虽然我怀疑它可能是我的同步块,谢谢。 主要方法类: 线程1: 线程2:

  • 问题内容: 我实现了此处描述的副本构造函数。但是问题仍然是,当我更新时,会将相同的更新应用于。所以,我不明白我的代码有什么问题? 问题答案: 在复制构造函数中,您只是在进行浅表复制,而您需要进行深表复制: 在这里,您仍在复制的引用,该引用仍指向same 。您也应该对其进行修改以创建列表的副本。可能还需要像下面这样在arraylist中创建元素的副本:

  • 我不懂pyplot。子地块(330 1 i)

  • 只读操作: 有没有办法有一个MongoDB副本集,但要使连接到的框上的MongoDB实例成为被查询的MongoDB? 我在AWS负载平衡器后面有三个EC2实例。 在每个EC2实例上运行MongoDB,它是副本集的一部分。 我在nodeJS上有expressendpoint,我连接到副本集,如下所示 我希望在MongoDB副本集的所有三个实例上均匀分布查询负载,而不是默认情况下将所有查询路由到定义了

  • 简单的赋值不会创建数组对象的副本。 相反,它使用原始数组的相同来访问它。 id()返回 Python 对象的通用标识符,类似于 C 中的指针。 此外,一个数组的任何变化都反映在另一个数组上。 例如,一个数组的形状改变也会改变另一个数组的形状。 我们的数组是: [0 1 2 3 4 5] 调用 id() 函数: 139747815479536 a 赋值给 b: [0 1 2 3 4 5] b 拥有相