Back to Stream Practice: Employee Analysis
Q33Question 33 of 43

Compute new salaries with department-based raise policy

Key Concepts
  • map() transforms each employee by applying the raise percentage based on their department
  • Use a Map<String, BigDecimal> to store raise percentages per department for flexible policy
  • BigDecimal arithmetic: salary.multiply(BigDecimal.ONE.add(raiseRate)) computes the new salary
  • Return new Employee objects (immutable) instead of mutating existing ones
  • getOrDefault on the policy map provides the fallback rate for unlisted departments
  • This tests map transformation with conditional logic based on element properties

Definition

Map each employee to a new Employee with salary adjusted by the department-specific raise percentage, using a policy Map for flexible rate lookup.
  • Policy map: Map maps department to raise rate (e.g., TRADING -> 0.10).
  • map(): transforms each employee by computing salary * (1 + raiseRate) using BigDecimal arithmetic.
  • getOrDefault: provides the fallback rate (5%) for departments not in the policy map.
  • Immutable design: create new Employee objects with the updated salary rather than mutating.

The bank announces raises: TRADING gets 10%, RISK gets 15%, everyone else gets 5%. Rajesh in TRADING gets 1800000 * 1.10 = 1980000. Priya in RISK gets 1000000 * 1.15 = 1150000.

Understanding the Concepts

How do you compute new salaries?

JAVA
package com.bank.hr;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

public class SalaryRaisePolicy {
    public static void main(String[] args) {
        List<Employee> employees = Employee.getSampleEmployees();

        Map<String, BigDecimal> policy = Map.of(
            "TRADING", new BigDecimal("0.10"),
            "RISK",    new BigDecimal("0.15"));
        BigDecimal defaultRate = new BigDecimal("0.05");

        List<Employee> updated = employees.stream()
            .map(e -> {
                BigDecimal rate = policy.getOrDefault(
                    e.getDepartment(), defaultRate);
                BigDecimal newSalary = e.getSalary()
                    .multiply(BigDecimal.ONE.add(rate))
                    .setScale(0, RoundingMode.HALF_UP);
                return e.withSalary(newSalary);
            })
            .toList();

        updated.forEach(e ->
            System.out.printf("%s (%s): Rs.%s%n",
                e.getName(), e.getDepartment(), e.getSalary()));
    }
}
TEXT
Rajesh (TRADING): Rs.1980000
Priya (RISK): Rs.1150000
Amit (RISK): Rs.1610000
Suresh (OPERATIONS): Rs.1155000

What are common mistakes?

Mistake: using double arithmetic for money.

JAVA
// WRONG: double loses precision
double wrong = 1800000.0 * 1.10;  // 1979999.9999999998

// CORRECT: BigDecimal
BigDecimal correct = new BigDecimal("1800000")
    .multiply(new BigDecimal("1.10"));  // 1980000.00

Mistake: mutating the original employee.

JAVA
// WRONG: mutates shared state
employees.forEach(e -> e.setSalary(
    e.getSalary().multiply(new BigDecimal("1.10"))));

// CORRECT: create new immutable objects
List<Employee> updated = employees.stream()
    .map(e -> e.withSalary(computeNew(e)))
    .toList();

What about computing the total raise cost?

JAVA
import java.math.BigDecimal;

BigDecimal totalCost = employees.stream()
    .map(e -> {
        BigDecimal rate = policy.getOrDefault(e.getDepartment(), defaultRate);
        return e.getSalary().multiply(rate);
    })
    .reduce(BigDecimal.ZERO, BigDecimal::add);

System.out.println("Total raise cost: Rs." + totalCost);

What about capping the raise at a maximum amount?

JAVA
BigDecimal maxRaise = new BigDecimal("200000");

List<Employee> capped = employees.stream()
    .map(e -> {
        BigDecimal rate = policy.getOrDefault(e.getDepartment(), defaultRate);
        BigDecimal raise = e.getSalary().multiply(rate);
        BigDecimal actualRaise = raise.min(maxRaise);
        return e.withSalary(e.getSalary().add(actualRaise));
    })
    .toList();

What about using a record for policy configuration?

JAVA
record RaisePolicy(String department, BigDecimal rate) {}

List<RaisePolicy> policies = List.of(
    new RaisePolicy("TRADING", new BigDecimal("0.10")),
    new RaisePolicy("RISK", new BigDecimal("0.15")));

Map<String, BigDecimal> policyMap = policies.stream()
    .collect(Collectors.toMap(
        RaisePolicy::department, RaisePolicy::rate));

What are the edge cases?

An employee in a department not in the policy map gets the default rate via getOrDefault. If the salary is BigDecimal.ZERO, the new salary is also zero regardless of the rate.

What are common interview follow-up questions?

  • "How do you compute total raise cost?" Sum the difference between new and old salaries.
  • "How do you cap the raise at a maximum amount?" Use BigDecimal.min(raise, cap).

Visual Overview

DIAGRAM
  Policy: TRADING=10%, RISK=15%, default=5%

  map(employee → updated employee)
  ┌──────────────────────────────────────────────────┐
  │  Rajesh  TRADING  1800K × 1.10 = 1980K           │
  │  Priya   RISK     1000K × 1.15 = 1150K           │
  │  Suresh  OPS      1100K × 1.05 = 1155K (default) │
  └──────────────────────────────────────────────────┘

Key Takeaway

Computing department-based salary raises uses a policy Map for flexible rate lookup and BigDecimal arithmetic for precision. Map each employee to a new Employee with the updated salary using salary.multiply(BigDecimal.ONE.add(rate)). Use getOrDefault for the fallback rate.

Remember one sentence: use a policy Map for department-specific rates, BigDecimal for money arithmetic, and map() to create new immutable Employee objects with updated salaries.

---

Share
Use ← → arrow keys to navigate