java—最有效的方法是什么?

mhd8tkvw  于 2021-07-06  发布在  Java
关注(0)|答案(3)|浏览(342)
float value = 0;
for (Foo foo : arrayList) {
    float temporaryValue = calculate(foo);
    if (temporaryValue < minValue) {
        continue;
    }   
    value = temporaryValue;
}

有没有可能在Java8中进行性能优化?例如使用不同的迭代方法或其他方法。

4xrmg8kj

4xrmg8kj1#

首先,简化顺序代码:

float value = 0;
for (Foo foo : arrayList) {
    float temporaryValue = calculate(foo);
    if (temporaryValue > minValue) {
        value = temporaryValue;
    }  
}

然后,如果arraylist上的元素数足够多,您可以尝试并行化代码。首先,使您的方法可并行化:

static void some_method(float[] values, int threadID, int total_threads){
    float value = 0;
    float minValue = Integer.MIN_VALUE;
    for (int i  = threadID; i < arrayList.size(); i+= total_threads) {
        float temporaryValue = calculate(arrayList.get(i));
        if (temporaryValue < minValue) {
            continue;
        }
        value = temporaryValue;
    }
   values[threadID] = value;
}

在上面的代码中,每个线程只负责从列表的一块中查找最大值(即。, for (int i = threadID; i < arrayList.size(); i+= total_threads) ). 最后,每个线程在值数组的相应位置更新(即,values[threadid]=value;),找到的最大值。这个更新应该在最后完成,以尽量减少潜在的错误共享开销。
现在创建线程,分配它们工作,并等待它们完成。

int total_threads = 2;
    float[] values = new float[total_threads];
    List<Thread> threads  = new ArrayList<>(total_threads);

    for(int i = 0; i < total_threads; i++){
        final int threadID = i;
        threads.add(new Thread(() -> some_method(values, threadID, total_threads)));
    }

    threads.forEach(Thread::start);
    threads.forEach(t -> {
        try {
            t.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
    // Calculate the maximum
    float max_value = Integer.MIN_VALUE;
    for (float v : values) {
        max_value = Math.max(v, max_value);
    }
}

在每个线程完成工作并找到它们的最大值后,主线程将从这些值中找出最大值:

float max_value = Integer.MIN_VALUE;
for (float v : values) {
    max_value = Math.max(v, max_value);
}

您可能希望进一步优化每个线程迭代的分布:

for (int i  = threadID; i < arrayList.size(); i+= total_threads)

取决于 calculate 方法,使用动态循环分布可能会有回报。

kyks70gy

kyks70gy2#

因为列表中满足条件的最后一个值“wins”,所以可以向后迭代,一旦第一个值大于或等于min值,就可以跳出循环。假设计算方法没有重要的副作用。

xzv2uavs

xzv2uavs3#

删除多余步骤:

if(temporaryValue > value) {
    value = temporaryValue;
}

或者只是 break 当你有一个值>= minValue .
或者使用java 8流:

final float value = (float) arrayList
    .stream()
    .mapToDouble(this::calculate)
    .max();

与基本循环相比,这不太可能提高性能,事实上,它可能更慢。但是,流可以很容易地并行化(或者至少比自定义多线程容易得多)。
但是你要问的第一个问题是我需要优化这个代码吗?你的单子有多大?这个代码多久被调用一次?问题有多复杂 calculate() 方法与迭代比较?

相关问题