![](/img/trans.png)
[英]Java Stream - maxBy - How to find a department with the highest Average salary with Java 8
[英]get average salary with Java stream api;
我如何獲得工資超過salaryLimit的公司員工的平均工資? 我想首先我需要獲得所有薪水的列表並對其進行過濾+使用 mapToInt 和平均值,但是......沒有任何效果((
public class TestCl {
@Data
@AllArgsConstructor
public class Company {
private List<Department> departments;
}
@Data
@AllArgsConstructor
public class Department {
private List<Employee> employees;
}
@Data
@AllArgsConstructor
public class Employee {
private int salary;
}
@Test
public void test() {
int salaryLimit = 25;
List<Employee> employees = new ArrayList<>(){{
add(new Employee(10));
add(new Employee(20));
add(new Employee(30));
add(new Employee(40));
add(new Employee(50));
}};
List<Department> departments = new ArrayList<>(){{
add(new Department(employees));
add(new Department(employees));
add(new Department(employees));
add(new Department(employees));
add(new Department(employees));
}};
Company company = new Company(departments);
float average = company.getDepartments().stream()
.map(Department::getEmployees).toList().stream()
.map(Employee::getSalary).toList().stream()
.filter(x -> x >= salaryLimit).mapToInt().average();
System.out.println(average);
}
}
一方面,您正在尋找Stream.flatMap()
。 例如,
company.getDepartments().stream()
.flatMap(d -> d.getEmployees().stream()) // ...
這會將您的Departments
的 stream 轉換為每個部門的Employees
的 stream。 然后,您可以將它們map()
到薪水並像您已經做的那樣進行過濾。
然而,組合.toList().stream()
意義,因為它將一個 stream 轉換為另一個提供完全相同對象的工作。 刪除它只有好處。
要將 map 轉換為IntStream
或者,為了這個目的可能更好,一個DoubleStream
, mapToInt()
或mapToDouble()
方法需要一個 function 來表達映射的細節,你忽略了。
最后, IntStream.average()
、 DoubleStream.average()
等返回一個OptionalInteger
/ OptionalDouble
/ etc ,它適應了由於 stream 提供零元素而沒有平均值的可能性。 你需要處理它。
一起,然后:
float average = company.getDepartments().stream() // a stream of Departments
.flatMap(d -> d.getEmployees().stream()) // a stream of Employees
.map(e -> e.getSalary()) // a stream of Integer salaries
.filter(s -> s.intValue() >= salaryLimit) // only the high salaries
.mapToDouble(Integer::doubleValue) // as a DoubleStream
.average() // reduce to an average
.getAsDouble(); // the value, if it exists
請注意,如果沒有薪水滿足過濾條件, getAsDouble()
將拋出NoSuchElementException
。 捕獲和處理是處理這種情況的一種完全合理的方法,但是如果你想避免這種情況,那么你可以存儲average()
的結果而不是鏈接getAsDouble()
,然后用isPresent()
測試它以確定是否使用getAsDouble()
提前到 go 或以不同方式處理這種情況。 或者,如果您想在這種情況下提供特定的double
精度值——例如0
或Double.NaN
那么您可以鏈接orElse(valueForZeroSalaries)
而不是getAsDouble()
。
你得到的是一個編譯器錯誤,因為mapToInt
需要一個ToIntFunction
但你沒有提供。
此外,您不需要將 stream 收集到列表中,只是為了再次將其轉換為 stream。 只要不調用終端方法,您仍然可以使用 stream。
所以你可以做的是這樣的:
double average = company.getDepartments().stream()
.flatMap(department -> department.getEmployees().stream())
.map(Employee::getSalary)
.filter(x -> x >= salaryLimit)
.mapToDouble(salary -> salary)
.average()
.orElse(0.0);
average()
給你一個Optional<Double>
所以你需要在最后打開值。 作為默認值,您可以通過調用orElse
返回0.0
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.