Мы продолжим нашу серию (Java против TypeScript (на примерах) — Часть 1 — Две суммы | Автор Rahul Bansal | Июль 2023 г. | Medium), а сегодня мы рассмотрим Java и TypeScript через еще одну красивую проблему. Проблема заявлена ​​как-

Имея список сотрудников с названиями их отделов, определите и выведите сотрудника со второй по величине зарплатой в каждом отделе.

Мы решим эту проблему как в Java, так и в TypeScript. Важно отметить, что мы также увидим, как красиво SQL решает эту проблему.

Начнем с SQL. Предполагая, что у вас есть таблица с именем «сотрудники» с такими столбцами, как «employee_id», «employee_name», «department» и «salary», вы можете использовать следующее:

SELECT department, employee_id, employee_name, salary
FROM (
    SELECT 
        department,
        employee_id,
        employee_name,
        salary,
        RANK() OVER (PARTITION BY department ORDER BY salary DESC) AS salary_rank
    FROM employees
) ranked_employees
WHERE salary_rank = 2;

SQL изначально поддерживает секционирование/группировку, упорядочивание/сортировку и ранжирование. Это облегчает поиск решения для любого ранга. Решение для самой высокой зарплаты в отделе еще проще:

SELECT department, employee_id, employee_name, MAX(salary) AS max_salary
FROM employees
GROUP BY department;

Теперь давайте попробуем добиться того же с помощью TypeScript.

class Employee
{
    constructor(
        public employeeId: number,
        public name: string,
        public department: string,
        public salary: number
    ) { }
}

// Assuming you have an array of Employee objects
const employees: Employee[] = [
    new Employee(1, "John Doe", "Sales", 50000),
    new Employee(2, "Jane Smith", "HR", 55000),
    new Employee(3, "Bob Johnson", "Sales", 60000),
    new Employee(4, "Alice Lee", "HR", 52000),
    new Employee(5, "Mike Williams", "Finance", 48000),
    new Employee(6, "Emily Brown", "Finance", 51000),
];

// Group employees by department using a Map
const employeesByDepartment = new Map<string, Employee[]>();
for (const employee of employees)
{
    if (!employeesByDepartment.has(employee.department))
    {
        employeesByDepartment.set(employee.department, []);
    }
    employeesByDepartment.get(employee.department)?.push(employee);
}

// Find the second highest salary in each department
for (const [department, departmentEmployees] of employeesByDepartment)
{

    if (departmentEmployees.length >= 2)
    {
        // Sort the employees within the department based on their salaries in descending order
        departmentEmployees.sort((a, b) => b.salary - a.salary);

        // Get the employee with the second highest salary
        const secondHighestSalaryEmployee = departmentEmployees[1];
        console.log(secondHighestSalaryEmployee);
        console.log("-------------------------");
    }
}

// Run with -> tsc .\second-highest-salary.ts --lib "es6,dom" --target "es2015"; node .\second-highest-salary.js

Довольно аккуратно. Сначала мы создали несколько сотрудников, а затем поместили их на карту (что эквивалентно группировке их по отделам). Затем мы прошлись по каждому отделу и использовали функцию сортировки, чтобы упорядочить всех сотрудников в отделе. А затем выбрали индекс 1, который является сотрудником со второй по величине зарплатой.

Следует отметить, что в отличие от SQL нет встроенной поддержки секционирования. Мы не можем сказать employeeArray.groupBy("отдел").orderBy("зарплата"). На мой взгляд, это должно поддерживаться языками высокого уровня.

А теперь попробуем то же самое на Java. Я выделю только ключевые части.

// Create a map to group employees by their departments
Map<String, List<Employee>> employeesByDepartment = new HashMap<>();
for (Employee employee : employees) 
{
    employeesByDepartment.computeIfAbsent(employee.getDepartment(), k -> new ArrayList<>()).add(employee);
}

// Find the second highest salary in each department
for (List<Employee> departmentEmployees : employeesByDepartment.values()) 
{
    if (departmentEmployees.size() >= 2) 
    { 
        departmentEmployees.sort(Comparator.comparingDouble(Employee::getSalary).reversed());

        // Get the employee with the second highest salary
        Employee secondHighestSalaryEmployee = departmentEmployees.get(1);

        // Print the result
        System.out.println("Employee ID: " + secondHighestSalaryEmployee.getEmployeeId());
        System.out.println("-------------------------");
    }
}

Практически идентично решению TypeScript (Эти два языка со временем стали очень близки друг к другу). Опять же, нет простого способа разделить данные. Нам нужно поместить сотрудников в карту, а затем отсортировать.

Итак, на этом мы завершаем сегодняшнюю дискуссию. Мы продолжим узнавать больше в следующих статьях. А пока удачного кодирования!