0

在具有 JSF 和 JPA 的 java ee 应用程序中,我必须计算对象列表中的属性总数。我使用 LambdaJ 库来实现总和的计算。

当我在应用程序的几个地方使用这种求和可能对整体性能产生影响时,我设计了以下测试 java 应用程序来测试 LambdaJ 的功效。

该应用程序表明 LambdaJ 严重缺乏功效。

测试程序中是否有任何错误,或者我应该用迭代替换所有出现的 lambdaJ 吗?

结果

Time taken to calculate a single total by iteration is 15 milliseconds.
Time taken to calculate a single total by LambdaJ is 199 milliseconds.
Time taken to calculate multiple totals by iteration is 23 milliseconds.
Time taken to calculate multiple totals by LambdaJ is 114 milliseconds.

主要方法

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.lakmedi;

import ch.lambdaj.Lambda;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 *
 * @author buddhika
 */
public class main {

    public static void main(String[] args) {
        List<Bill> bills = new ArrayList<>();
        Random r = new Random();
        for (int i = 0; i < 100000; i++) {
            Bill b = new Bill();
            b.setGrossTotal(r.nextDouble());
            b.setDiscount(r.nextDouble());
            b.setNetTotal(b.getGrossTotal() - b.getDiscount());
            bills.add(b);
        }
        calSingleByIteration(bills);
        calSingleByLambdja(bills);
        calMultipleByIteration(bills);
        calMultipleByLambdja(bills);
    }

    public static void calSingleByIteration(List<Bill> bills) {
        Date startTime = new Date();
        double grossTotal = 0.0;
        for (Bill b : bills) {
            grossTotal += b.getGrossTotal();
        }
        Date endTime = new Date();
        long timeTaken = endTime.getTime() - startTime.getTime();
        System.out.println("Time taken to calculate a single total by iteration is " + timeTaken + " milliseconds.");
    }

    public static void calSingleByLambdja(List<Bill> bills) {
        Date startTime = new Date();
        double grossTotal = Lambda.sumFrom(bills).getGrossTotal();
        Date endTime = new Date();
        long timeTaken = endTime.getTime() - startTime.getTime();
        System.out.println("Time taken to calculate a single total by LambdaJ is " + timeTaken + " milliseconds.");
    }

    public static void calMultipleByIteration(List<Bill> bills) {
        Date startTime = new Date();
        double grossTotal = 0.0;
        double discount = 0.0;
        double netTotal = 0.0;
        for (Bill b : bills) {
            grossTotal += b.getGrossTotal();
            discount += b.getDiscount();
            netTotal += b.getNetTotal();
        }
        Date endTime = new Date();
        long timeTaken = endTime.getTime() - startTime.getTime();
        System.out.println("Time taken to calculate multiple totals by iteration is " + timeTaken + " milliseconds.");
    }

    public static void calMultipleByLambdja(List<Bill> bills) {
        Date startTime = new Date();
        double grossTotal = Lambda.sumFrom(bills).getGrossTotal();
        double discount = Lambda.sumFrom(bills).getDiscount();
        double netTotal = Lambda.sumFrom(bills).getNetTotal();
        Date endTime = new Date();
        long timeTaken = endTime.getTime() - startTime.getTime();
        System.out.println("Time taken to calculate multiple totals by LambdaJ is " + timeTaken + " milliseconds.");
    }

}

比尔类

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package com.lakmedi;

/**
 *
 * @author buddhika
 */
public class Bill {
    private double grossTotal;
    private double netTotal;
    private double discount;

    public double getGrossTotal() {
        return grossTotal;
    }

    public void setGrossTotal(double grossTotal) {
        this.grossTotal = grossTotal;
    }

    public double getNetTotal() {
        return netTotal;
    }

    public void setNetTotal(double netTotal) {
        this.netTotal = netTotal;
    }

    public double getDiscount() {
        return discount;
    }

    public void setDiscount(double discount) {
        this.discount = discount;
    }


}
4

2 回答 2

3

假设您的意思是效率而不是功效,那么您测量的性能或多或少符合预期 - 请参阅 LambdaJ 自己的性能分析

使用 Java 8 Lambda 表达式可能会获得更好的结果,但这里的主要目标是提高源代码的可读性和可维护性,而不是提高速度。您确定执行求和所需的时间对应用程序的整体性能至关重要吗?我怀疑它是否考虑了 HTTP 流量 (JSF) 和数据库查询 (JPA) 的 (I/O) 等待时间,在这种情况下这是过早的优化(万恶之源)。

于 2014-08-17T00:08:10.553 回答
2

首先,检查您使用的是最新版本的 LambdaJ,因为项目站点表明最新版本有一些性能改进。

但是,我认为您应该期望 lambdaj 比编写等效的 for 循环要慢。在更简洁的语法背后,JVM 做了更多的工作。

您可以考虑放弃 lambdaj 并使用 Java 8 流和 lambda 表达式。

以下是 lambdaj 的作者对此事的看法:

Lemme 再次澄清这一点:Java8 发布后,我认为开发/维护#lambdaj 没有任何意义。迁移到 Java8 并快乐

——马里奥·福斯科,2014 年 5 月

于 2014-08-17T00:09:37.703 回答