簡體   English   中英

如何從 Java 中的列表中找到過濾元素的平均值

[英]How do I find the average of filtered elements from list in Java

我希望找到給定年份特定分支機構的平均銷售額。 有一個列表,其中包含所有分支機構和所有銷售年份。 我嘗試使用 IntStream 來過濾具有所需年份和分支的元素,但我無法找到平均值,indexOfSaleInTheYear.size() 中顯示錯誤,我不確定平均值部分代碼是否為正確的。 請幫忙。 謝謝你。

Scanner avgSale = new Scanner(System.in);
    System.out.println("Please enter the year for average sale: \n");
    int yearEntered = avgSale.nextInt();

    Scanner branchNameForAvg = new Scanner(System.in);
    System.out.println("Please enter the branch name whose average sale is to be found, case sensitive: \n");
    String branchNameEntered = branchNameForAvg.nextLine();

    Stream<Integer> indexOfSalesInTheYear = IntStream.of(0, Sale.allValues.size()).boxed()
            .filter(i -> Sale.allYears.get(i).equals(yearEntered))
            .filter(i -> Sale.allBranches.get(i).equals(branchNameEntered));
    
    int sum = 0;
    for(int j = 0; j < indexOfSalesInTheYear.size(); j++){
        sum += j;
    }
    double avgSaleFinal = sum/indexOfSalesInTheYear.size();

    System.out.println("The average sale for the year " + yearEntered + " is " + avgSaleFinal + ".");
    }

這是我將如何處理它。 有一個包含這些字段的對象列表,而不是單獨的值、年份和分支列表:

record Sale(int value, int year, String branch) {
}

在這里,我使用的是record ,但如果您願意,需要具有可變的Sale實例,或者正在使用 Java 的早期版本,您可以調整此代碼以使用具有普通 getter 和 setter 的類。

List<Sale> sales = List.of(
    new Sale(12, 2020, "east"),
    new Sale(15, 2020, "west"),
    new Sale(13, 2020, "east"),
    new Sale(16, 2020, "west"),
    new Sale(14, 2020, "east"),
    new Sale(17, 2020, "west"),
    new Sale(18, 2021, "east"),
    new Sale(19, 2021, "west"));

double averageOfSales(int year, String branchName) {
    OptionalDouble average = sales.stream()
        .filter(sale -> sale.year() == year)
        .filter(sale -> sale.branch().equals(branchName))
        .mapToInt(sale -> sale.value())
        .average();
    return average.orElseThrow(() ->
        new NoSuchElementException("no matching year and branch"));
}

您可能只想返回OptionalDouble或拋出一個不同的異常; 這完全取決於您要如何處理沒有提供年份和分支名稱的值的情況。 在這種情況下,您甚至可能只想return 0.0或 NaN 或 -1.0 或其他一些標記值。

不需要自己對值求和或除以值的數量來求平均值,因為IntStream已經有求和或求平均值的方法。

保持不同的數據片段分開,並行結構是新的 Java 程序員的常見模式,但它確實違背了面向 object 的編程或什至只是抽象數據類型的概念。 您不需要單獨保留 collections 的簡單值; 您可以創建自己的類型,包括值、年份、分支機構、月份、門牌號、郵政編碼以及您想要的任何其他類型 model 作為您正在使用的數據域的一部分。

在您現有的代碼中,您永遠不會迭代allValues列表。 由於您使用的是流,因此您可以這樣做。

double average = IntStream.of(0, Sale.allValues.size()-1) // go up to the last index only
                .filter(i -> Sale.allYears.get(i).equals(yearEntered))
                .filter(i -> Sale.allBranches.get(i).equals(branchNameEntered))
                .mapToDouble(i -> Sale.allValues.get(i)) // now you have every sale value for yearEntered and branchNameEntered
                .average().orElse(-1); // or if not present, throw error, or get the optional, etc

實際上,您不應該有單獨的列表,您應該有一個 Sale 對象列表。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM