ItTechGenie-Subject - Java Stream API (Warm-up + 10 Questions)

Java Question Bank

Java Stream API | Q0 Warm‑up (Show/Hide Answer) + Q1–Q10 Scenario Questions (5 Moderate + 5 Complex) — With Answers

Instruction: Boilerplate is visible by default. Students implement ONLY methods marked // ✅ TODO.
Answers: Available via Show/Hide Answer.
Warm‑up: 1 (Q0) Moderate: 5 (Q1–Q5) Complex: 5 (Q6–Q10) Inputs: spaces + quotes + unicode α/β + emoji ✅ + special chars
0

Warm‑up: stream() + filter/map/collect (with answer)

stream()filtermapcollectWarm-up

Warm‑up: Given a list of prices as strings (may contain spaces and currency symbols), create a stream pipeline that: 1) trims each value 2) removes currency symbols like ₹, $ 3) converts to Integer 4) keeps only values >= 100 5) collects to List<Integer> Implement ONLY: warmUp() to print the final list.

✅ Includes spaces + quotes + unicode α/β + emoji ✅ + special chars.
Java Stream API scenario (students implement ONLY // ✅ TODO)Ctrl+C
import java.util.*;
import java.util.stream.*;

public class Main {

    // ✅ TODO: Student must implement only this method
    static void warmUp() {
        // TODO:
        // - create list of strings
        // - build stream pipeline: trim -> remove symbols -> parse -> filter >=100 -> collect
        // - print the result list
        throw new UnsupportedOperationException("TODO");
    }

    public static void main(String[] args) {
        warmUp();
    }
}

Answer (Logic + Code)

Logic: - stream(): processes a collection in a pipeline - map(): transforms each element - filter(): keeps elements that match a condition - collect(toList()): turns stream back into a List

static void warmUp() {
    List<String> prices = Arrays.asList("  ₹99  ", " $120 ", "  250✅ ", "  80 ", "  ₹150  ");

    List<Integer> out = prices.stream()
            .map(s -> s.trim())                                  // remove surrounding spaces
            .map(s -> s.replaceAll("[^0-9]", ""))                // keep digits only
            .filter(s -> !s.isEmpty())                           // safety
            .map(Integer::parseInt)                              // to integer
            .filter(v -> v >= 100)                               // business rule
            .collect(Collectors.toList());                       // back to list

    System.out.println(out);
}
1

Distinct normalized usernames — trim + lowercase + distinct

mapdistinctcollectModerate

Scenario: Your login audit sends usernames with random casing and extra spaces. Task: - trim each username - convert to lowercase - remove empty values - return distinct usernames (preserve encounter order) Implement ONLY: UserOps.distinctUsers(List<String> raw) Print result.

✅ Includes spaces + quotes + unicode α/β + emoji ✅ + special chars.
Java Stream API scenario (students implement ONLY // ✅ TODO)Ctrl+C
import java.util.*;
import java.util.stream.*;
import java.util.function.*;
import java.util.regex.*;

class UserOps {
    // ✅ TODO: Student must implement only this method
    static List<String> distinctUsers(List<String> raw) {
        // TODO:
        // - null safe
        // - stream -> trim -> lowercase -> filter non-empty -> distinct -> collect
        throw new UnsupportedOperationException("TODO");
    }
}

public class Main {
    public static void main(String[] args) {
        List<String> raw = Arrays.asList("  Gopi  ", "gopi", " GOPI ", "Suresh✅", "  suresh✅  ", "  ", "α/β");
        System.out.println(UserOps.distinctUsers(raw));
    }
}

Answer (Logic + Code)

Use stream() + map(String::trim) + map(String::toLowerCase) + filter(s -> !s.isBlank()) + distinct() + collect(toList()).

static List<String> distinctUsers(List<String> raw) {
    if (raw == null) return java.util.Collections.emptyList();
    return raw.stream()
            .map(s -> s == null ? "" : s.trim())         // null-safe trim
            .map(String::toLowerCase)                    // normalize
            .filter(s -> !s.isBlank())                   // remove blanks
            .distinct()                                  // unique in encounter order
            .collect(java.util.stream.Collectors.toList());
}
2

Top‑N expensive orders — sort + limit + map

sortedComparatorlimitModerate

Scenario: You have orders with totalAmount (may include currency symbols). Task: - parse totals as double - sort descending by amount - take top N (N given) - return List<String> of orderIds Implement ONLY: OrderOps.topNOrderIds(List<Order> orders, int n) Print result.

✅ Includes spaces + quotes + unicode α/β + emoji ✅ + special chars.
Java Stream API scenario (students implement ONLY // ✅ TODO)Ctrl+C
import java.util.*;
import java.util.stream.*;

class Order {
    final String id;            // order id (may include spaces/special chars)
    final String total;         // amount as text (may include symbols/spaces)
    Order(String id, String total){ this.id=id; this.total=total; }
}

class OrderOps {
    // ✅ TODO: Student must implement only this method
    static List<String> topNOrderIds(List<Order> orders, int n) {
        // TODO:
        // - parse numeric value from total
        // - sort desc by numeric amount
        // - limit n
        // - map to id
        throw new UnsupportedOperationException("TODO");
    }

    // helper (you may call this from stream)
    static double parseAmount(String s){
        String t = (s==null?"":s).trim().replaceAll("[^0-9.]", "");
        return t.isEmpty()?0.0:Double.parseDouble(t);
    }
}

public class Main {
    public static void main(String[] args) {
        List<Order> orders = Arrays.asList(
            new Order("ORD 1","₹1200.50"),
            new Order("ORD-α2","  $ 999.99 "),
            new Order("ORD✅3","₹1200.50"),
            new Order("ORD 4","₹10"),
            new Order("ORD 5","₹2500")
        );
        System.out.println(OrderOps.topNOrderIds(orders, 3));
    }
}

Answer (Logic + Code)

Use Comparator.comparingDouble(o -> parseAmount(o.total)) then reversed(), limit(n), map(o -> o.id).

static List<String> topNOrderIds(List<Order> orders, int n) {
    if (orders == null || n <= 0) return java.util.Collections.emptyList();

    return orders.stream()
            .sorted(java.util.Comparator.comparingDouble(o -> parseAmount(o.total)).reversed())
            .limit(n)
            .map(o -> o.id)
            .collect(java.util.stream.Collectors.toList());
}
3

Group purchases by category — groupingBy + summingInt

groupingBysummingIntModerate

Scenario: You are building a dashboard: total quantity sold per category. Task: - group items by category (case-insensitive, trim) - sum quantities per category - return Map<String,Integer> Implement ONLY: SalesOps.qtyByCategory(List<Item> items) Print map.

✅ Includes spaces + quotes + unicode α/β + emoji ✅ + special chars.
Java Stream API scenario (students implement ONLY // ✅ TODO)Ctrl+C
import java.util.*;
import java.util.stream.*;

class Item {
    final String name;     // item name
    final String category; // category (messy text)
    final int qty;         // quantity
    Item(String name, String category, int qty){ this.name=name; this.category=category; this.qty=qty; }
}

class SalesOps {
    // ✅ TODO: Student must implement only this method
    static Map<String,Integer> qtyByCategory(List<Item> items) {
        // TODO:
        // - normalize category: trim + lowercase
        // - groupingBy(category, summingInt(qty))
        throw new UnsupportedOperationException("TODO");
    }
}

public class Main {
    public static void main(String[] args) {
        List<Item> items = Arrays.asList(
            new Item("Phone"," Electronics ",2),
            new Item("Cable","electronics",3),
            new Item("Tea"," Grocery✅ ",5),
            new Item("Rice","grocery✅",1),
            new Item("Pen","Stationery",10)
        );
        System.out.println(SalesOps.qtyByCategory(items));
    }
}

Answer (Logic + Code)

Collectors.groupingBy(normalizedCategory, Collectors.summingInt(i -> i.qty))

static Map<String,Integer> qtyByCategory(List<Item> items) {
    if (items == null) return java.util.Collections.emptyMap();

    return items.stream()
            .collect(java.util.stream.Collectors.groupingBy(
                    i -> (i.category == null ? "" : i.category.trim().toLowerCase()),
                    java.util.stream.Collectors.summingInt(i -> i.qty)
            ));
}
4

Partition emails — partitioningBy(valid?)

partitioningByregexModerate

Scenario: Support team collects emails from a CSV import. Task: - partition into valid and invalid buckets - return Map<Boolean, List<String>> Rules: - trim each email - valid if matches basic pattern: something@something.something Implement ONLY: EmailOps.partitionValid(List<String> emails) Print map.

✅ Includes spaces + quotes + unicode α/β + emoji ✅ + special chars.
Java Stream API scenario (students implement ONLY // ✅ TODO)Ctrl+C
import java.util.*;
import java.util.regex.*;
import java.util.stream.*;

class EmailOps {
    static final Pattern P = Pattern.compile("^[^@\s]+@[^@\s]+\.[^@\s]+$");

    // ✅ TODO: Student must implement only this method
    static Map<Boolean, List<String>> partitionValid(List<String> emails) {
        // TODO:
        // - trim
        // - partitioningBy(email -> P.matcher(email).matches())
        throw new UnsupportedOperationException("TODO");
    }
}

public class Main {
    public static void main(String[] args) {
        List<String> emails = Arrays.asList(" gopi@ittechgenie.com ", "bad@@mail", "suresh✅@mail.com", " α/β@x.io ", "no-domain@x", "");
        System.out.println(EmailOps.partitionValid(emails));
    }
}

Answer (Logic + Code)

Use stream().map(trim).collect(partitioningBy(predicate)).

static Map<Boolean, List<String>> partitionValid(List<String> emails) {
    if (emails == null) return java.util.Collections.emptyMap();

    return emails.stream()
            .map(s -> s == null ? "" : s.trim())
            .collect(java.util.stream.Collectors.partitioningBy(s -> P.matcher(s).matches()));
}
5

Flatten tags + count frequency — flatMap + groupingBy(counting)

flatMapcountingfrequencyModerate

Scenario: Each product has a tags string separated by '|'. Task: - split tags - trim + lowercase - ignore blanks - count frequency of each tag Return Map<String,Long> Implement ONLY: TagOps.countTags(List<String> tagLines) Print map.

✅ Includes spaces + quotes + unicode α/β + emoji ✅ + special chars.
Java Stream API scenario (students implement ONLY // ✅ TODO)Ctrl+C
import java.util.*;
import java.util.stream.*;

class TagOps {
    // ✅ TODO: Student must implement only this method
    static Map<String,Long> countTags(List<String> tagLines) {
        // TODO:
        // - flatMap split by \|
        // - normalize
        // - groupingBy(tag, counting())
        throw new UnsupportedOperationException("TODO");
    }
}

public class Main {
    public static void main(String[] args) {
        List<String> tagLines = Arrays.asList(" fast | eco | ✅ ", "Eco| durable|fast", " α/β | eco | ", "durable|");
        System.out.println(TagOps.countTags(tagLines));
    }
}

Answer (Logic + Code)

flatMap(line -> Arrays.stream(line.split("\\|"))) then normalize, groupingBy(identity, counting).

static Map<String,Long> countTags(List<String> tagLines) {
    if (tagLines == null) return java.util.Collections.emptyMap();

    return tagLines.stream()
            .filter(Objects::nonNull)
            .flatMap(line -> java.util.Arrays.stream(line.split("\\|")))
            .map(s -> s.trim().toLowerCase())
            .filter(s -> !s.isBlank())
            .collect(java.util.stream.Collectors.groupingBy(
                    s -> s,
                    java.util.LinkedHashMap::new,
                    java.util.stream.Collectors.counting()
            ));
}
6

Build report with custom Collector — join lines with numbering

CollectorStringBuilderjoiningComplex

Scenario: You must build a human-readable multi-line report from errors: Example output: 1) ERR-01 | message 2) ERR-α2 | message ✅ Rules: - keep order - add numbering starting from 1 - join with '\n' Implement ONLY: ReportOps.build(List<Err> errs) Print report.

✅ Includes spaces + quotes + unicode α/β + emoji ✅ + special chars.
Java Stream API scenario (students implement ONLY // ✅ TODO)Ctrl+C
import java.util.*;
import java.util.stream.*;

class Err {
    final String code;
    final String msg;
    Err(String code, String msg){ this.code=code; this.msg=msg; }
}

class ReportOps {
    // ✅ TODO: Student must implement only this method
    static String build(List<Err> errs) {
        // TODO:
        // - use IntStream range to number lines
        // - or use stream with mutable counter (AtomicInteger)
        // - build one multi-line string
        throw new UnsupportedOperationException("TODO");
    }
}

public class Main {
    public static void main(String[] args) {
        List<Err> errs = Arrays.asList(
            new Err("ERR-01","Invalid  pin  \"123\""),
            new Err("ERR-α2","Payment failed ✅"),
            new Err("ERR-03","City=Ben@luru!")
        );
        System.out.println(ReportOps.build(errs));
    }
}

Answer (Logic + Code)

Use IntStream.range(0, list.size()) to preserve order and add numbering deterministically.

static String build(List<Err> errs) {
    if (errs == null || errs.isEmpty()) return "";

    return java.util.stream.IntStream.range(0, errs.size())
            .mapToObj(i -> {
                Err e = errs.get(i);
                String code = e.code == null ? "" : e.code.trim();
                String msg  = e.msg  == null ? "" : e.msg.trim().replaceAll("\\s+", " ");
                return (i + 1) + ") " + code + " | " + msg;
            })
            .collect(java.util.stream.Collectors.joining("\n"));
}
7

Compute median amount — mapToDouble + sorted + skip/limit

mapToDoublesortedmedianComplex

Scenario: For analytics, compute the median transaction amount. Rules: - parse amount from messy strings (₹, $, spaces) - sort numeric values - if odd => middle element - if even => average of two middle elements Implement ONLY: StatsOps.median(List<String> amounts) Print median.

✅ Includes spaces + quotes + unicode α/β + emoji ✅ + special chars.
Java Stream API scenario (students implement ONLY // ✅ TODO)Ctrl+C
import java.util.*;
import java.util.stream.*;

class StatsOps {
    static double parseAmount(String s){
        String t = (s==null?"":s).trim().replaceAll("[^0-9.]", "");
        return t.isEmpty()?0.0:Double.parseDouble(t);
    }

    // ✅ TODO: Student must implement only this method
    static double median(List<String> amounts) {
        // TODO:
        // - map to double
        // - sort
        // - compute median for odd/even size
        throw new UnsupportedOperationException("TODO");
    }
}

public class Main {
    public static void main(String[] args) {
        List<String> a = Arrays.asList("₹10", " $ 20 ", "₹30✅", " 40 ", "₹100", "₹200");
        System.out.println(StatsOps.median(a));
    }
}

Answer (Logic + Code)

Collect sorted doubles into a list/array, then compute median by index.

static double median(List<String> amounts) {
    if (amounts == null || amounts.isEmpty()) return 0.0;

    double[] arr = amounts.stream()
            .mapToDouble(StatsOps::parseAmount)
            .sorted()
            .toArray();

    int n = arr.length;
    if (n % 2 == 1) return arr[n / 2];
    return (arr[n / 2 - 1] + arr[n / 2]) / 2.0;
}
8

Parallel stream: count unique cities safely (normalize + concurrent set)

parallelStreamthread-safetycollectComplex

Scenario: You process a huge list of city strings and want count of unique normalized cities. Rule: - normalize (trim + lowercase) - ignore blanks - must be safe with parallelStream() Implement ONLY: CityOps.uniqueCount(List<String> cities) Print count.

✅ Includes spaces + quotes + unicode α/β + emoji ✅ + special chars.
Java Stream API scenario (students implement ONLY // ✅ TODO)Ctrl+C
import java.util.*;
import java.util.stream.*;
import java.util.concurrent.*;

class CityOps {
    // ✅ TODO: Student must implement only this method
    static long uniqueCount(List<String> cities) {
        // TODO:
        // - parallel stream
        // - normalize
        // - collect into a concurrent set OR use distinct() (works, but explain)
        throw new UnsupportedOperationException("TODO");
    }
}

public class Main {
    public static void main(String[] args) {
        List<String> cities = Arrays.asList(" Bengaluru ", "bengaluru", "Chennai✅", "  ", "BENGALURU", "α/β City", "α/β city");
        System.out.println(CityOps.uniqueCount(cities));
    }
}

Answer (Logic + Code)

distinct() is safe for parallel streams; alternatively collect into ConcurrentHashMap.newKeySet().

static long uniqueCount(List<String> cities) {
    if (cities == null) return 0;

    return cities.parallelStream()
            .map(s -> s == null ? "" : s.trim().toLowerCase())
            .filter(s -> !s.isBlank())
            .distinct()
            .count();
}
9

Running total (cumulative sum) — stream with mutable state (careful)

running totalstateSequential streamComplex

Scenario: Generate a running total of daily sales for a chart. Input is list of integers as strings (may include spaces and emoji). Rules: - parse ints - produce List<Integer> runningTotals (same length) Important: - This must be done in a SEQUENTIAL stream (stateful operation) Implement ONLY: Running.total(List<String> daily) Print list.

✅ Includes spaces + quotes + unicode α/β + emoji ✅ + special chars.
Java Stream API scenario (students implement ONLY // ✅ TODO)Ctrl+C
import java.util.*;
import java.util.stream.*;

class Running {
    static int parseIntSafe(String s){
        String t = (s==null?"":s).replaceAll("[^0-9-]", "").trim();
        return t.isEmpty()?0:Integer.parseInt(t);
    }

    // ✅ TODO: Student must implement only this method
    static List<Integer> total(List<String> daily) {
        // TODO:
        // - sequential stream only
        // - build running totals
        throw new UnsupportedOperationException("TODO");
    }
}

public class Main {
    public static void main(String[] args) {
        List<String> daily = Arrays.asList(" 10 ", "20✅", "  5", "15", "α/β 30");
        System.out.println(Running.total(daily));
    }
}

Answer (Logic + Code)

Use an int[1] accumulator (or AtomicInteger) in a sequential stream; do NOT use this with parallel streams.

static List<Integer> total(List<String> daily) {
    if (daily == null) return java.util.Collections.emptyList();

    final int[] sum = new int[]{0}; // mutable holder
    return daily.stream()                                   // sequential by default
            .map(Running::parseIntSafe)
            .map(v -> sum[0] += v)                           // running total
            .collect(java.util.stream.Collectors.toList());
}
10

Top product per category — groupingBy + maxBy + collectingAndThen

groupingBymaxByOptionalComplex

Scenario: For each category, find the product with maximum revenue. Revenue = price * qty. Rules: - category normalization: trim + lowercase - return Map<String, Product> (one top product per category) Implement ONLY: ProductOps.topByCategory(List<Product> products) Print map (category -> productId).

✅ Includes spaces + quotes + unicode α/β + emoji ✅ + special chars.
Java Stream API scenario (students implement ONLY // ✅ TODO)Ctrl+C
import java.util.*;
import java.util.stream.*;

class Product {
    final String id;
    final String category;
    final double price;
    final int qty;
    Product(String id, String category, double price, int qty){
        this.id=id; this.category=category; this.price=price; this.qty=qty;
    }
    double revenue(){ return price * qty; }
}

class ProductOps {
    // ✅ TODO: Student must implement only this method
    static Map<String, Product> topByCategory(List<Product> products) {
        // TODO:
        // - group by normalized category
        // - pick max revenue product per category
        // - unwrap Optional
        throw new UnsupportedOperationException("TODO");
    }
}

public class Main {
    public static void main(String[] args) {
        List<Product> p = Arrays.asList(
            new Product("P1","Electronics ", 999.0, 2),
            new Product("P2","electronics", 1200.0, 1),
            new Product("P3","Grocery✅", 50.0, 20),
            new Product("P4","grocery✅ ", 80.0, 5),
            new Product("P5","Stationery", 10.0, 100)
        );

        Map<String, Product> out = ProductOps.topByCategory(p);
        out.forEach((k,v) -> System.out.println(k + " -> " + (v==null? "null" : v.id)));
    }
}

Answer (Logic + Code)

Use groupingBy + collectingAndThen(maxBy(comparingDouble(Product::revenue)), opt -> opt.orElse(null)).

static Map<String, Product> topByCategory(List<Product> products) {
    if (products == null) return java.util.Collections.emptyMap();

    return products.stream()
            .collect(java.util.stream.Collectors.groupingBy(
                    pr -> (pr.category == null ? "" : pr.category.trim().toLowerCase()),
                    java.util.stream.Collectors.collectingAndThen(
                            java.util.stream.Collectors.maxBy(java.util.Comparator.comparingDouble(Product::revenue)),
                            opt -> opt.orElse(null)
                    )
            ));
}