首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用Java在两个相同维度的列表之间进行元素级乘法

如何使用Java在两个相同维度的列表之间进行元素级乘法
EN

Stack Overflow用户
提问于 2022-08-09 17:44:59
回答 2查看 97关注 0票数 3

我有两份清单如下:

代码语言:javascript
运行
复制
List<Double> margins =  Arrays.asList(1.0,2.0,3.0,4.0,5.0);
List<Integer> quantity = Arrays.asList(1,2,3,4,5);

我想在它们之间做元素乘法,我知道我可以用标准的for循环来实现它,但是我想知道我们是否可以通过Stream来实现同样的过程,使这个过程更快,更少的资源?

类似于Python对NumPy数组所做的事情;与其制作一个for循环,而是矢量化,从而使其更快。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-08-10 08:52:48

,类似于Python对numpy数组所做的事情;与其做一个for循环,不如将矢量化,这使得它更快。

如果您对感兴趣,那么Stream就是,而不是您要寻找的

因为Java16我们将作为一个 (这意味着它不是API的最终状态,而是用于测试和收集反馈,您不应该在生产中使用它)。

为了在Java中使用孵化器特性,您需要做一些额外的工作来从导入的孵化器模块获取文件。

确保从包jdk.incubator.vector导入类的方法之一是创建一个模块,以显式指定它需要这个包。

考虑一个具有以下文件夹结构的简单测试项目:

代码语言:javascript
运行
复制
- [src]
  - [main]
    - [java]
      - module-info.java
      - [vectorization.test]
        - Main.java
      - resources

// other things

module-info.java --这里我们请求Vector的文件:

代码语言:javascript
运行
复制
module vectorization.test {
    requires jdk.incubator.vector;
}

Main.java

代码语言:javascript
运行
复制
package vectorization.test;

import jdk.incubator.vector.DoubleVector;
import jdk.incubator.vector.VectorSpecies;

import java.util.Arrays;

public class Main {
    
    public static void main(String[] args) {
        double[] margins = {1.0, 2.0, 3.0, 4.0, 5.0};
        double[] quantity = {1, 2, 3, 4, 5};
        double[] result = new double[margins.length];
    
        multiply(margins, quantity, result);
    
        System.out.println(Arrays.toString(result));
    }
    
    public static final VectorSpecies<Double> SPECIES = DoubleVector.SPECIES_PREFERRED;
    
    public static void multiply(double[] margins, double[] quantity, double[] result) {
        int i = 0;
        for (; i < SPECIES.loopBound(margins.length); i += SPECIES.length()) {
            DoubleVector marginsVector = DoubleVector.fromArray(SPECIES, margins, i);
            DoubleVector quantityVector = DoubleVector.fromArray(SPECIES, quantity, i);
            DoubleVector resultVector = marginsVector.mul(quantityVector);
            resultVector.intoArray(result, i);
        }
        for (; i < margins.length; i++) {
            result[i] = margins[i] * quantity[i];
        }
    }
}

输出:

代码语言:javascript
运行
复制
[1.0, 4.0, 9.0, 16.0, 25.0]

有关Vector的更多信息,请查看。

说到流,它们并不比普通循环(如果是顺序流)更具有性能,实际上它们是较慢的,因为流需要创建额外的对象来执行迭代、进行转换和积累结果。这里没有魔法。

并行流可能更快,但它是一个应该谨慎使用的工具,因为您也可能得到相反的效果。您需要您的任务是可并行的,您的线程应该有空闲的CPU内核来完成这项工作,并且数据量应该很大,以使并行流的使用变得合理(并且仍然需要测量性能以确定它在您的情况下是否起作用)。

在Java中引入函数式编程特性的主要目标之一是提供一种简洁和可读的方法来构造代码。

例如,如何使用Arrays.setAll()填充生成的产品数组

代码语言:javascript
运行
复制
Arrays.setAll(result, i -> margins[i] * quantity[i]);
票数 3
EN

Stack Overflow用户

发布于 2022-08-09 18:01:52

您可以通过流将数组的元素相乘,但它不会比传统的循环更有效。然而,对于如此小的数据集,开销非常小,不会产生任何影响。

下面是通过流实现的方法。基本上,您可以使用IntStream类将两个列表从0迭代到最小列表的大小(不包括)。然后,将每个int索引映射到一个双重对象,该对象表示margins列表的第一个元素的乘积和quantity列表的第一个元素,最后将结果收集到一个List<Double>中。

代码语言:javascript
运行
复制
List<Double> margins = Arrays.asList(1.0, 2.0, 3.0, 4.0, 5.0);
List<Integer> quantity = Arrays.asList(1, 2, 3, 4, 5);

List<Double> res = IntStream.range(0, Math.min(margins.size(), quantity.size()))
        .mapToObj(i -> margins.get(i) * quantity.get(i))
        .collect(Collectors.toList());
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73296071

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档