Yes, you can learn Java Collections and Streams in 14 days if each day has one small, concrete task and a way to check your own answer. This plan uses invoice data, which is close to what enterprise Java code actually processes, and ends with a self-check key and a recap table so you can see what you have covered.
Why invoices make a good practice dataset for Java Collections and Streams
Most enterprise Java work is about records: orders, invoices, customers, payments. Each record has a few fields, there are many of them, and the business wants questions answered: who owes the most, which month had the highest sales, which invoices are overdue. Collections store those records, and streams answer those questions in a few readable lines.
Textbook exercises with lists of integers teach syntax but not judgement. An invoice list forces real decisions: should this be a List or a Map? Is a duplicate invoice number a bug or valid data? What should happen when a field is missing? Those decisions are what interviewers and reviewers care about.
If you want a structured place to practise, CareerSwami offers a free two-week online internship with a free offer letter and a free completion certificate after successful completion. The plan below fits that 14-day window, but it works equally well as a solo challenge.
The shared setup: one Invoice record and sample data
Create one small project with a single class and reuse it every day. The code below is illustrative and is meant for you to type and run yourself.
import java.time.LocalDate;
import java.math.BigDecimal;
public record Invoice(
String invoiceNo,
String customer,
String city,
LocalDate date,
BigDecimal amount,
boolean paid
) {}
Build a method List<Invoice> sample() that returns 15 to 20 invoices. Make the data deliberately imperfect:
- At least three customers with more than one invoice.
- Invoices across at least three months and three cities.
- A mix of paid and unpaid invoices.
- One duplicate invoice number and one invoice with a zero amount, to test your handling on later days.
Use BigDecimal for money rather than double, because floating-point rounding errors in currency are a classic enterprise bug.
Free 2-Week CareerSwami Internship
Online, 14 days, with a free offer letter and a free completion certificate once you finish the work. Check with your college that it fits your requirement before you enrol.
The 14-day micro-task plan, from List basics to a final report
Each task should take 30 to 60 minutes. Write the solution first, then compare with the key further down.
Days 1 to 5: Collections foundations
- Day 1, List. Store the sample invoices in an
ArrayList. Print each one with an enhanced for loop, then remove all invoices with a zero amount usingremoveIf. - Day 2, sorting. Sort invoices by amount descending using
Comparator.comparing. Then sort by customer name, with ties broken by date. - Day 3, Set. Put all invoice numbers into a
HashSetand detect the duplicate by checking the return value ofadd. Then tryLinkedHashSetandTreeSetand note how the order differs. - Day 4, Map. Build a
Map<String, List<Invoice>>grouping invoices by customer using a loop andcomputeIfAbsent. - Day 5, Map totals. Build a
Map<String, BigDecimal>of total billed per customer usingmerge. Print it in alphabetical order withTreeMap.
Days 6 to 10: Stream pipelines
- Day 6, filter and map. Using a stream, list the invoice numbers of all unpaid invoices above 10,000.
- Day 7, reduce and sum. Compute total unpaid amount with
mapandreduce(BigDecimal.ZERO, BigDecimal::add). - Day 8, groupingBy. Rebuild the Day 4 map in one statement with
Collectors.groupingBy. Compare line counts and readability. - Day 9, downstream collectors. Use
groupingBywithsummingInt,countingor aBigDecimalreducer to get invoice count and total per city. - Day 10, partitioning and Optional. Use
partitioningBy(Invoice::paid)and find the largest unpaid invoice withmax, handling theOptionalresult without callingget()blindly.
Days 11 to 14: Realistic reporting and review
- Day 11, date logic. Find invoices older than 30 days that are unpaid, relative to a fixed reference date you pass in, so the result is repeatable.
- Day 12, monthly summary. Group by
YearMonthand produce a sorted month-by-month total usingTreeMapas the map factory. - Day 13, top N and joining. Produce the top three customers by total billed and print them as one comma-separated line using
Collectors.joining. - Day 14, mini report. Combine earlier tasks into a console report: duplicate warnings, per-city totals, overdue list, top customers. Add three simple tests of your own for the edge cases.
Worked illustrative example: unpaid totals per customer on Day 9
This is an illustrative sketch with made-up numbers, not output from a run. Suppose the data holds these unpaid invoices:
| Invoice | Customer | City | Amount (₹) |
|---|---|---|---|
| INV-101 | Asha Traders | Nagpur | 12,000 |
| INV-102 | Asha Traders | Nagpur | 8,000 |
| INV-103 | Mehta Stores | Bhopal | 5,000 |
The task: total unpaid per customer. A first attempt might be:
Map<String, BigDecimal> unpaidByCustomer = invoices.stream()
.filter(i -> !i.paid())
.collect(Collectors.groupingBy(
Invoice::customer,
TreeMap::new,
Collectors.reducing(BigDecimal.ZERO, Invoice::amount, BigDecimal::add)
));
By hand, the expected result is Asha Traders 20,000 and Mehta Stores 5,000. Work out the expected answer on paper before running anything; if your program disagrees, you have found either a bug or a misunderstanding, and either is useful. Then ask what happens with a null customer name. groupingBy throws a NullPointerException on a null key, so decide whether to filter such invoices out or map them to “UNKNOWN”.
Self-check key: what a correct answer must show for each day
Rather than full solutions, this key lists the observable result and the trap to look for. Match your output against it.
| Day | Your result should show | Common trap |
|---|---|---|
| 1 | Zero-amount invoices gone, list size reduced by that count | Removing inside a for-each loop causes ConcurrentModificationException |
| 2 | Highest amount first; ties ordered by date | Comparing BigDecimal with == or subtracting values |
| 3 | Duplicate invoice number reported exactly once | Ignoring that add returns false for duplicates |
| 4 | Each customer key maps to all their invoices | Overwriting the list with put instead of appending |
| 5 | Totals equal the sum of that customer’s amounts | Using HashMap and expecting sorted output |
| 6 | Only unpaid invoices above 10,000 appear | Filtering on paid instead of not paid |
| 7 | Total matches a manual addition | Using double and seeing rounding noise |
| 8 | Same map contents as Day 4 | Assuming the map type is guaranteed; it is not unless you specify it |
| 9 | Count and total per city agree with a spreadsheet | Counting after the wrong filter |
| 10 | Two groups, true and false; max handled safely | Calling get() on an empty Optional |
| 11 | Same result every run for the same reference date | Using LocalDate.now() inside the logic |
| 12 | Months in chronological order | Grouping by month name, which sorts alphabetically |
| 13 | Three names, highest total first | Sorting ascending and taking the first three |
| 14 | Report runs end to end; three edge-case tests pass | Testing only the happy path |
Recap table: concepts, APIs and the question each one answers
| Concept | Key APIs | Business question it answers | Days |
|---|---|---|---|
| Lists and sorting | ArrayList, removeIf, Comparator |
Show invoices in a useful order | 1-2 |
| Sets | HashSet, TreeSet |
Are any invoice numbers duplicated? | 3 |
| Maps | computeIfAbsent, merge, TreeMap |
What does each customer owe? | 4-5 |
| Basic streams | filter, map, reduce |
What is outstanding in total? | 6-7 |
| Collectors | groupingBy, partitioningBy, counting |
Totals by city, paid versus unpaid | 8-10 |
| Dates and ordering | LocalDate, YearMonth |
What is overdue, and how did each month go? | 11-12 |
| Ranking and output | sorted, limit, joining |
Who are our top customers? | 13 |
| Integration | All of the above, plus tests | One report a manager could read | 14 |
How to run each day so the habit actually sticks
- Write the expected answer by hand before running code.
- Commit to a Git repository daily, with a one-line message naming the day and the concept.
- Keep a short notes file with one thing that surprised you each day.
- On Days 8, 11 and 14, rewrite an earlier solution in a cleaner way and compare.
- Do not copy a stream chain you cannot explain line by line. If you cannot say what type flows out of each step, break it into named variables.
Raja Shankar Shah University students: what is known and what to check before you build this into coursework
Raja Shankar Shah University, formerly Chhindwara University, is described by Wikipedia as a state university in Chhindwara, Madhya Pradesh. That page is a secondary source, not an official university page, and it gives 2019 as the founding year. It also says the university has jurisdiction over four districts: Balaghat, Betul, Chhindwara and Seoni, though that line is tagged “citation needed” there. Treat all of this as background and check the current official information.
What this means for your Java practice: nothing about the plan above depends on the university. It needs only a laptop, a JDK and an editor. What does depend on your university or college is whether this work can be shown in a project, lab record or internship report, and in what format. Rules on internship duration, evaluation, documents and whether an online internship is accepted may be set by the university, by your college, or by your department, and that is not something to assume.
Do not assume the 14-day plan carries academic credit. CareerSwami’s internship offers a free offer letter and completion certificate; it does not promise credit, a stipend or placement.
Verification steps:
- Open the official university website (confirm the correct address from your admit card, fee receipt or college notice board rather than a search result) and look for the notices or academic section.
- Ask your department office in writing whether your scheme includes a summer or semester-break internship, and whether an online one is acceptable.
- Request the current syllabus for your programme and check whether Java, collections or object-oriented programming appear in your semester.
- Ask your college’s training and placement cell, if one exists, what certificate or report format it wants.
- Ask whether rules come from the university or from your affiliated college, and get the answer in an email or notice you can keep.
Turning the 14 days into something you can show
By Day 14 you should have a small repository with the Invoice record, 14 small solutions, three tests and a README. Write the README as if a reviewer will read only that: what the project does, how to run it, and three design decisions (for example, why BigDecimal, why TreeMap for monthly output, how duplicates are handled).
In interviews, describe one decision per day rather than listing APIs. “I used partitioningBy because I needed both groups, including the empty one” shows more understanding than naming ten collectors.
Once the plan feels comfortable, extend the same data in new directions: read invoices from a CSV file, add a Payment record and join it to invoices through a map, or compare a parallel stream with a sequential one on a larger generated dataset, and measure rather than assume.
Frequently Asked Questions
Do I need to know Java well before starting this plan?
You should be comfortable with classes, methods, loops and basic generics. Records and lambdas are introduced as you go, but if you have never written a Java class, spend a couple of days on basics first.
Which Java version do I need?
Records need Java 16 or later, so use a current long-term support release. If your lab machines are older, replace the record with a normal class with a constructor and getters; the collection and stream tasks stay the same.
Why use BigDecimal instead of double for invoice amounts?
Floating-point numbers cannot represent many decimal values exactly, so sums can drift by tiny amounts. Money code uses BigDecimal to keep results exact and predictable.
When should I use a loop instead of a stream?
Use a loop when the logic has several steps with side effects, early exits or complicated state. Use a stream when you are filtering, transforming, grouping or summarising. Days 4 and 8 deliberately solve the same problem both ways so you can judge.
Is HashMap order reliable for my report output?
No. HashMap makes no ordering guarantee. Use TreeMap for sorted keys or LinkedHashMap for insertion order whenever output order matters.
Will completing this plan count as an internship or credit at my university?
That depends on your university and college rules, which you should confirm in writing with your department. The CareerSwami internship provides a free offer letter and a free completion certificate after successful completion, but no academic credit is promised.
What if I miss a day?
Do the missed task next, then continue. The tasks build on the shared Invoice data, so skipping Days 4 to 5 will make Days 8 to 9 harder. If you fall behind by more than two days, drop the Day 13 extension and keep Day 14.
How do I know my stream solution is correct?
Compute the expected answer by hand on a small subset, compare it with your output, and write at least one test for an empty list and one for a null or zero-amount case.
Related Java & Enterprise Software guides
- Sidho-Kanho-Birsha University: Making a Capstone Java Project Out of an Internship Task
- Goa University Students: Java Internship Options in Local Tourism and Hospitality Software
- Dhanalakshmi Srinivasan University: A Mid-Internship Self-Review Worksheet for Java Learners
- All Java & Enterprise Software internship guides
Ready to put this into practice?
Join the free two-week CareerSwami online internship in Java & Enterprise Software. The internship, the offer letter and the completion certificate are free.










