|
|
import java.time.LocalDate;
|
|
|
import java.time.Period;
|
|
|
import java.util.*;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
/**
|
|
|
* 员工统计类 - 负责生成复杂的统计报告
|
|
|
* 遵循单一职责原则:只负责员工数据的统计分析逻辑
|
|
|
*/
|
|
|
public class EmployeeStatistics {
|
|
|
|
|
|
/**
|
|
|
* 计算员工薪资总额
|
|
|
* @param employees 员工列表
|
|
|
* @return 薪资总额
|
|
|
*/
|
|
|
public double calculateTotalSalary(List<Employee> employees) {
|
|
|
return employees.stream()
|
|
|
.mapToDouble(Employee::getSalary)
|
|
|
.sum();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 计算员工平均薪资
|
|
|
* @param employees 员工列表
|
|
|
* @return 平均薪资
|
|
|
*/
|
|
|
public double calculateAverageSalary(List<Employee> employees) {
|
|
|
if (employees.isEmpty()) {
|
|
|
return 0;
|
|
|
}
|
|
|
return calculateTotalSalary(employees) / employees.size();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取最高薪资
|
|
|
* @param employees 员工列表
|
|
|
* @return 最高薪资
|
|
|
*/
|
|
|
public double getMaxSalary(List<Employee> employees) {
|
|
|
if (employees.isEmpty()) {
|
|
|
return 0;
|
|
|
}
|
|
|
return employees.stream()
|
|
|
.mapToDouble(Employee::getSalary)
|
|
|
.max()
|
|
|
.orElse(0);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取最低薪资
|
|
|
* @param employees 员工列表
|
|
|
* @return 最低薪资
|
|
|
*/
|
|
|
public double getMinSalary(List<Employee> employees) {
|
|
|
if (employees.isEmpty()) {
|
|
|
return 0;
|
|
|
}
|
|
|
return employees.stream()
|
|
|
.mapToDouble(Employee::getSalary)
|
|
|
.min()
|
|
|
.orElse(0);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 计算部门薪资分布
|
|
|
* @param employees 员工列表
|
|
|
* @return 部门薪资分布映射(部门 -> 薪资统计)
|
|
|
*/
|
|
|
public Map<String, DepartmentSalaryStats> calculateDepartmentSalaryDistribution(List<Employee> employees) {
|
|
|
return employees.stream()
|
|
|
.collect(Collectors.groupingBy(Employee::getDepartment))
|
|
|
.entrySet().stream()
|
|
|
.collect(Collectors.toMap(
|
|
|
Map.Entry::getKey,
|
|
|
entry -> {
|
|
|
List<Employee> deptEmployees = entry.getValue();
|
|
|
double totalSalary = deptEmployees.stream().mapToDouble(Employee::getSalary).sum();
|
|
|
double avgSalary = deptEmployees.isEmpty() ? 0 : totalSalary / deptEmployees.size();
|
|
|
double maxSalary = deptEmployees.stream().mapToDouble(Employee::getSalary).max().orElse(0);
|
|
|
double minSalary = deptEmployees.stream().mapToDouble(Employee::getSalary).min().orElse(0);
|
|
|
return new DepartmentSalaryStats(totalSalary, avgSalary, maxSalary, minSalary, deptEmployees.size());
|
|
|
}
|
|
|
));
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 计算员工年龄分布
|
|
|
* @param employees 员工列表
|
|
|
* @return 年龄分布映射(年龄段 -> 人数)
|
|
|
*/
|
|
|
public Map<String, Long> calculateAgeDistribution(List<Employee> employees) {
|
|
|
return employees.stream()
|
|
|
.collect(Collectors.groupingBy(
|
|
|
e -> {
|
|
|
int age = e.getAge();
|
|
|
if (age < 25) return "25岁以下";
|
|
|
else if (age < 35) return "25-34岁";
|
|
|
else if (age < 45) return "35-44岁";
|
|
|
else if (age < 55) return "45-54岁";
|
|
|
else return "55岁以上";
|
|
|
},
|
|
|
Collectors.counting()
|
|
|
));
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 计算员工司龄分布
|
|
|
* @param employees 员工列表
|
|
|
* @return 司龄分布映射(司龄段 -> 人数)
|
|
|
*/
|
|
|
public Map<String, Long> calculateTenureDistribution(List<Employee> employees) {
|
|
|
return employees.stream()
|
|
|
.collect(Collectors.groupingBy(
|
|
|
e -> {
|
|
|
int tenure = e.getTenure();
|
|
|
if (tenure < 1) return "不足1年";
|
|
|
else if (tenure < 3) return "1-2年";
|
|
|
else if (tenure < 5) return "3-4年";
|
|
|
else if (tenure < 10) return "5-9年";
|
|
|
else return "10年以上";
|
|
|
},
|
|
|
Collectors.counting()
|
|
|
));
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 计算部门人数分布
|
|
|
* @param employees 员工列表
|
|
|
* @return 部门人数分布映射(部门 -> 人数)
|
|
|
*/
|
|
|
public Map<String, Long> calculateDepartmentHeadcount(List<Employee> employees) {
|
|
|
return employees.stream()
|
|
|
.collect(Collectors.groupingBy(Employee::getDepartment, Collectors.counting()));
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取指定年份入职的员工数
|
|
|
* @param employees 员工列表
|
|
|
* @param year 年份
|
|
|
* @return 该年份入职的员工数
|
|
|
*/
|
|
|
public long getHireCountByYear(List<Employee> employees, int year) {
|
|
|
return employees.stream()
|
|
|
.filter(e -> e.getHireDate().getYear() == year)
|
|
|
.count();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 计算性别分布(如果Employee类中有性别属性)
|
|
|
* 这里作为示例,假设Employee类有gender属性
|
|
|
* @param employees 员工列表
|
|
|
* @return 性别分布映射(性别 -> 人数)
|
|
|
*/
|
|
|
// 由于Employee类中没有性别属性,此方法作为示例保留
|
|
|
public Map<String, Long> calculateGenderDistribution(List<Employee> employees) {
|
|
|
// 实际实现需要在Employee类中添加gender属性
|
|
|
System.out.println("注意:Employee类中暂未添加性别属性,无法计算性别分布");
|
|
|
return new HashMap<>();
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 获取薪资排名前N的员工
|
|
|
* @param employees 员工列表
|
|
|
* @param n 数量
|
|
|
* @return 薪资最高的N名员工
|
|
|
*/
|
|
|
public List<Employee> getTopNSalaryEmployees(List<Employee> employees, int n) {
|
|
|
if (n <= 0) {
|
|
|
throw new IllegalArgumentException("N必须为正整数");
|
|
|
}
|
|
|
|
|
|
return employees.stream()
|
|
|
.sorted(Comparator.comparingDouble(Employee::getSalary).reversed())
|
|
|
.limit(n)
|
|
|
.collect(Collectors.toList());
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 计算在职率
|
|
|
* @param employees 员工列表
|
|
|
* @return 在职率(百分比)
|
|
|
*/
|
|
|
public double calculateActiveRate(List<Employee> employees) {
|
|
|
if (employees.isEmpty()) {
|
|
|
return 0;
|
|
|
}
|
|
|
long activeCount = employees.stream()
|
|
|
.filter(Employee::isActive)
|
|
|
.count();
|
|
|
return (double) activeCount / employees.size() * 100;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* 部门薪资统计内部类
|
|
|
*/
|
|
|
public static class DepartmentSalaryStats {
|
|
|
private final double totalSalary;
|
|
|
private final double averageSalary;
|
|
|
private final double maxSalary;
|
|
|
private final double minSalary;
|
|
|
private final int headcount;
|
|
|
|
|
|
public DepartmentSalaryStats(double totalSalary, double averageSalary,
|
|
|
double maxSalary, double minSalary, int headcount) {
|
|
|
this.totalSalary = totalSalary;
|
|
|
this.averageSalary = averageSalary;
|
|
|
this.maxSalary = maxSalary;
|
|
|
this.minSalary = minSalary;
|
|
|
this.headcount = headcount;
|
|
|
}
|
|
|
|
|
|
public double getTotalSalary() { return totalSalary; }
|
|
|
public double getAverageSalary() { return averageSalary; }
|
|
|
public double getMaxSalary() { return maxSalary; }
|
|
|
public double getMinSalary() { return minSalary; }
|
|
|
public int getHeadcount() { return headcount; }
|
|
|
|
|
|
@Override
|
|
|
public String toString() {
|
|
|
return "部门薪资统计{" +
|
|
|
"总薪资= " + totalSalary +
|
|
|
", 平均薪资= " + String.format("%.2f", averageSalary) +
|
|
|
", 最高薪资= " + maxSalary +
|
|
|
", 最低薪资= " + minSalary +
|
|
|
", 人数= " + headcount +
|
|
|
"}";
|
|
|
}
|
|
|
}
|
|
|
} |