SPEAKER NOTES 01
Press N to toggle
BACKEND 101

Intermediate
C++
& Basic Java

Memory · OOP · STL · JVM · Streams
A technical primer for backend fundamentals

30 slides 2 languages 1 session
auto ptr = make_unique<Dog>("Rex");
ptr->bark();
public class Main {
  System.out.println("Hello!");
}
ROADMAP

What
We
Cover

30slides
2parts
01–03

C++ Memory

Stack, heap, pointers & smart pointers

04–06

C++ OOP

Encapsulation, inheritance, polymorphism

07–09

STL & Templates

Containers, algorithms, generic code

10–12

Modern C++

Lambdas, move semantics, exceptions

13–21

Java Core

JVM, types, OOP, collections, streams

22–24

C++ vs Java

Tradeoffs, performance, real-world use

PART 01 · SLIDES 04 – 18

Intermediate
C++

Memory  ·  OOP  ·  STL  ·  Modern Features

C++11C++14C++17
C++
C++ · MEMORY04

Stack vs Heap

Stack

AUTOLifetime tied to scope — erased when function returns
FASTJust moves one pointer — extremely CPU cache-friendly
LIFOLast in, first out — like a literal stack of plates
LIMITFixed size at compile time — typically 1 to 8 MB
int x = 5; // stack — gone when } runs

Heap

MANUALAllocate with new, free with delete
FLEXAny size, determined at runtime
SLOWSlower — allocator must do bookkeeping
RISKForget to free = leak. Free twice = crash.
int* p = new int(5); delete p;
Prefer the stack unless you need dynamic size, a lifetime beyond a single function, or shared data across scopes.
C++ · MEMORY05

Raw Pointers

What is a pointer?

A variable that stores a memory address. Use & to get an address, * to read or write through it. The pointer IS NOT the value — it is a map to where the value lives.

Pointer Arithmetic

Adding 1 advances by sizeof(T) bytes. arr + 3 points to the 4th element. Useful for traversing arrays — dangerous if you go out of bounds.

The Three Danger Zones

Dangling pointer — points to freed memory. Double-free — calling delete twice crashes your program. Null dereference — accessing nullptr causes a segfault. Always set to nullptr after deleting.

When raw pointers are still used

OS kernels, embedded systems, C API interop, performance-critical inner loops. Everywhere else — prefer smart pointers.

C++
int val = 42;
int* ptr = &val;
*ptr = 100;
int* arr = new int[5];
for (int i = 0; i < 5; ++i)
  arr[i] = i * 10;
delete[] arr;
arr = nullptr;
int nums[] = {10, 20, 30};
int* p = nums;
*(p + 2) = 99;
C++ · SMART POINTERS06

unique_ptr

Sole Ownership

One and only one unique_ptr owns the resource. It cannot be copied — only moved. This enforces clear, unambiguous ownership in your architecture.

Automatic Cleanup — RAII

When the unique_ptr goes out of scope its destructor calls delete automatically. Memory cannot leak. Zero overhead compared to a raw pointer.

Always use make_unique

Exception-safe, no redundant type names, prevents half-constructed objects. Available C++14 onwards. Prefer it over new 100% of the time in modern code.

Transfer with std::move

Ownership can be transferred explicitly: auto b = std::move(a). After the move, a becomes nullptr. The transfer of responsibility is visible in the code.

C++14
#include <memory>
auto p = make_unique<int>(42);
*p = 100;
auto dog = make_unique<Dog>("Rex");
dog->bark();
auto p2 = std::move(p);
int* raw = p2.get();
C++ · SMART POINTERS07

shared_ptr &
weak_ptr

shared_ptr — Reference Counting

Multiple pointers share one resource. An internal counter tracks owners. Memory is freed only when the count reaches zero.

Circular Reference — The Leak

If A owns B and B owns A through shared_ptrs, the count never hits zero. Memory leaks permanently. This is the most common shared_ptr bug.

weak_ptr — Non-Owning Observer

Does not increment the count. Must call lock() to get a temporary shared_ptr. Safely detects whether the object has already been freed.

The Rule

Use shared_ptr for true shared ownership. Use weak_ptr for back-references, caches, and observer patterns — anywhere you observe without owning.

C++
auto s1 = make_shared<string>("hello");
auto s2 = s1;
s1.use_count();
weak_ptr<string> w = s1;
if (auto locked = w.lock()) {
  cout << *locked;
}
s1.reset();
s2.reset();
w.expired();
C++ · OOP08

The Four OOP Pillars

Encapsulation

Bundle data and methods together. Hide internals with private. Only expose a clean public surface. Like a TV remote — press buttons, do not see the circuit board.

class Dog {
private: int age;
public: void bark();
};

Inheritance

A derived class IS-A base class. Reuse and extend behaviour. Lab is-a Dog is-an Animal. Use : public Base to inherit.

class Lab
: public Dog {
public: void fetch();
};

Polymorphism

Same interface, different behaviour. Runtime dispatch via vtable. virtual plus override. Say speak — Dog barks, Cat meows.

virtual void
speak() = 0;

void speak()
override {}

Abstraction

Expose WHAT to do, hide HOW it is done. Pure virtual equals zero creates abstract interfaces that derived classes must fill in.

class Shape {
virtual double
area() = 0;
};
C++ · OOP09

Encapsulation
& Classes

Access Specifiers

private — this class only. protected — this class and derived classes. public — everyone. Default in class is private. Default in struct is public.

Initializer List — Always Use It

Constructs members directly rather than default-constructing and then assigning. Faster and required for const members and references.

const Methods

A const method promises it will not modify this object. Enables calling on const references and self-documents intent.

Rule of Zero

If you use smart pointers and STL types for all resources you need zero special copy, move, or destructor logic. The compiler generates correct behaviour for free.

C++
class Dog {
private:
  string name;
  int age;
public:
  Dog(string n, int a)
    : name(n), age(a) {}
  string getName() const {
    return name;
  }
  void setAge(int a) {
    if (a > 0) age = a;
  }
};
C++ · OOP10

Inheritance

IS-A Relationship

Derived class IS-A base class. Use only for true IS-A relationships, not just to reuse code. Lab is-a Dog — that works. Reusing code between unrelated classes — use composition instead.

Constructor Chaining

Base constructor runs first. Chain it via initializer list: Lab(string n) : Dog(n, 1) {}. Destruction runs in reverse — derived destroyed first, then base.

Multiple Inheritance & Diamond

C++ allows multiple parents. The Diamond Problem: two paths lead to the same grandparent causing duplicate copies. Solved with virtual base classes.

Virtual Destructor — Always

Any class with virtual methods must have a virtual destructor. Otherwise deleting through a base pointer causes undefined behaviour — the derived destructor never runs.

C++
class Animal {
protected:
  string name;
public:
  Animal(string n) : name(n) {}
  virtual ~Animal() = default;
  virtual void speak() = 0;
};
class Dog : public Animal {
public:
  Dog(string n) : Animal(n) {}
  void speak() override {
    cout << name << ": Woof!";
  }
};
C++ · STL11

STL Containers

ContainerAccessInsert / EraseSorted?Best For
vector<T>O(1)O(1) amort. at end Default — cache-friendly sequence
deque<T>O(1)O(1) both endsFast front and back access
list<T>O(n)O(1) anywhereFrequent mid-sequence edits
map<K,V>O(log n)O(log n) YesSorted key-value, range queries
unordered_map<K,V>O(1) avgO(1) avg Fastest key-value lookups
set<T>O(log n)O(log n)YesUnique sorted elements
priority_queue<T>O(1) topO(log n)HeapAlways get the largest element first
Start with vector. Switch only after profiling shows a bottleneck.
list has poor cache locality — often slower than vector even for frequent mid-inserts.
C++ · TEMPLATES12

Templates

Function Templates

Write once, works for any type. The compiler generates type-specific versions at compile time. Zero runtime overhead — full optimisation per type.

Class Templates

Parameterise an entire class. Every STL container is a class template — vector<T>, map<K,V>. Type safety is enforced at compile time.

Template Specialisation

Provide a custom implementation for a specific type when the generic version is not optimal. For example a Stack<bool> that uses bitwise storage.

vs Java Generics

C++ generates unique code per type — faster but larger binary. Java uses type erasure — one bytecode, type checked at compile time only. Different tradeoffs entirely.

C++
template<typename T>
T maxVal(T a, T b) {
  return a > b ? a : b;
}
maxVal(3, 7);
maxVal(3.14, 2.72);
maxVal("a", "z");
template<typename T>
class Stack {
  vector<T> data;
public:
  void push(T v) { data.push_back(v); }
  T top() { return data.back(); }
};
C++ · MODERN C++11+13

Lambda Expressions

Syntax

[capture](params) { body }
Capture brings in outer variables. Params are arguments. Body is the work.

Capture Modes

[=] capture all by value (copy)
[&] capture all by reference
[x, &y] mixed

auto vs std::function

auto stores a lambda with zero overhead and the compiler can inline it. std::function adds type erasure and runtime cost — use it only when you need polymorphic storage.

Perfect for STL

Replaces separate functor classes entirely. Pass inline to sort, find_if, transform. Cleaner than writing a named struct just for one comparator.

C++11
auto greet = [](string name) {
  cout << "Hello, " << name;
};
greet("World");
int threshold = 50;
auto isAbove = [&threshold](int x) {
  return x > threshold;
};
vector<int> v = {5,2,8,1};
sort(v.begin(), v.end(),
  [](int a, int b){ return a > b; });
C++ · MODERN C++11+14

Move Semantics

lvalue vs rvalue

lvalue: named, persists — like int x = 5. rvalue: temporary, about to die — like 42 or foo(). T&& binds to rvalues only.

Move Constructor — Steal, Not Copy

Grabs the internal buffer and nulls out the source. Order one regardless of data size. Critical for returning large objects from functions efficiently.

std::move — Cast to Rvalue

Tells the compiler you give up ownership. Enables the move constructor instead of the copy constructor. The source is empty after — do not read it.

noexcept Required

Mark move constructors noexcept or STL containers like vector will fall back to copying during reallocation. The noexcept guarantee is checked at compile time.

C++11
class Buffer {
  int* data;
  size_t sz;
public:
  Buffer(Buffer&& o) noexcept
    : data(o.data), sz(o.sz) {
    o.data = nullptr;
    o.sz = 0;
  }
};
Buffer a(1024);
Buffer b = std::move(a);
C++ · MODERN C++11+15

Exception Handling

throw by value, catch by const&

Throw creates a copy. Catching by const reference avoids another copy and prevents object slicing. Catch most-specific exceptions first, the base class last.

Standard Exception Hierarchy

std::exception is the root. Children include runtime_error, logic_error, bad_alloc, out_of_range. Catch the base to handle all of them in one block.

No finally — RAII Instead

Destructors run even during exception unwinding. Smart pointers and lock_guard auto-clean up. This is more reliable than finally because you cannot forget to write it.

noexcept

Promise the function will not throw. Enables compiler optimisations. Required for move constructors to be used by STL containers during reallocation.

C++
#include <stdexcept>
double divide(double a, double b) {
  if (b == 0.0)
    throw runtime_error("div by zero");
  return a / b;
}
try {
  auto r = divide(10.0, 0.0);
} catch (const runtime_error& e) {
  cerr << e.what();
} catch (...) {
  cerr << "unknown error";
}
PART 02 · SLIDES 17 – 28

Basic
Java

JVM  ·  OOP  ·  Collections  ·  Streams

Java 8Java 11Java 17
Java
JAVA · JVM17

JVM Architecture

1
Java Source
.java file — human-readable code
↓ javac compiler
2
Bytecode
.class file — platform-independent
↓ JVM Classloader
3
JVM Runtime
Interpreter + JIT compiler
↓ hot path compilation
4
Native Machine Code
Near-native speed on frequently run paths

Write Once, Run Anywhere

Bytecode is OS-agnostic. Any machine with a JVM runs the same dot class file — Windows, Linux, macOS, Android, smart cards.

Garbage Collector

Automatically reclaims heap memory. Modern GCs: G1GC is default, ZGC and Shenandoah for ultra-low pause. No manual delete ever needed.

JIT — Smarter Over Time

Profiles runtime behaviour and compiles hot methods to native code. Long-running Java servers often match C++ speed after the JVM warms up.

JAVA · TYPES18

Java Types
& Variables

Primitives (Stack)

byte, short, int, long, float, double, boolean, char. Stored by value. Fast. Cannot be null.

Reference Types (Heap)

String, arrays, all objects. Variable holds a reference. All classes inherit from Object. Can be null — which is the source of the NPE.

Autoboxing

Java auto-converts primitive to wrapper and back. int to Integer is implicit. Convenient — but pay attention in performance-sensitive loops.

var (Java 10+)

Local type inference. Compiler infers the type from the initializer expression. Only valid for local variables — not fields or parameters.

Java
int x = 42;
long big = 9_000_000_000L;
boolean ok = true;
Integer boxed = x;
int back = boxed;
String s = "hello";
s = s + "!";
var sb = new StringBuilder();
sb.append("hello").append("!");
var list = new ArrayList<String>();
JAVA · OOP19

Java Classes
& Objects

Everything is a class

No free functions, no global variables. Everything lives inside a class. The entry point is public static void main taking a String array.

All Objects Inherit Object

toString, equals, and hashCode are inherited by every object. Always override equals and hashCode together — HashMap depends on this contract being correct.

No Destructor — try-with-resources

GC handles memory. For files and connections: use try-with-resources with AutoCloseable. The close method is called automatically even when an exception fires.

Access Modifiers

public, protected, package-private (the default, no keyword), private. The default is package-private — stricter than C++.

Java
public class Dog {
  private String name;
  private int age;
  public Dog(String name, int age) {
    this.name = name;
    this.age = age;
  }
  public String getName() { return name; }
  @Override
  public String toString() {
    return name + " (age " + age + ")";
  }
}
JAVA · OOP20

Interfaces &
Abstract Classes

interface — Pure Contract

Defines WHAT, not HOW. All methods are implicitly public and abstract. A class can implement any number of interfaces — Java's answer to multiple inheritance.

default methods (Java 8+)

Interfaces can have concrete methods via the default keyword. Allows adding new methods to existing interfaces without breaking every class that implements them.

abstract class

Can have fields, constructors, and a mix of concrete and abstract methods. Use for shared state across subclasses. You can extend only one abstract class.

Interface vs Abstract Class

Interface for capability contracts: Flyable, Comparable, Runnable. Abstract class for partial implementation with shared data. When in doubt: interface.

Java
interface Flyable {
  void fly();
  default void land() {
    System.out.println("Landing...");
  }
}
interface Swimmable { void swim(); }
class Duck extends Animal
    implements Flyable, Swimmable {
  @Override public void fly() { ... }
  @Override public void swim() { ... }
}
JAVA · COLLECTIONS21

Java Collections Framework

InterfaceImplementationOrdered?Duplicates?C++ Equivalent
ListArrayListInsertion orderYesvector<T>
ListLinkedListInsertion orderYeslist<T>
MapHashMapNoKeys: Nounordered_map<K,V>
MapTreeMapSorted by keyKeys: Nomap<K,V>
SetHashSetNoNounordered_set<T>
SetTreeSetSortedNoset<T>
QueuePriorityQueueHeap orderYespriority_queue<T>
Default: ArrayList for lists, HashMap for key-value. Switch only with good reason.
None are thread-safe. Use ConcurrentHashMap in multithreaded code.
JAVA · GENERICS22

Java Generics

Type Safety at Compile Time

Before generics ArrayList held Object — runtime ClassCastException risk. Generics catch type mismatches at compile time. Much safer development.

Type Erasure — Key Difference from C++

Generic info is erased at runtime. List<String> becomes List in bytecode. You cannot write new T() or use instanceof T at runtime because the JVM does not know what T is.

Bounded Type Parameters

T extends Comparable<T> restricts T to types that implement Comparable. Enables calling compareTo inside the generic code safely.

Wildcards — PECS Rule

Producer Extends, Consumer Super. Question mark extends T means read from it. Question mark super T means write to it.

Java
class Pair<A, B> {
  private final A first;
  private final B second;
  Pair(A a, B b) { first=a; second=b; }
  A getFirst() { return first; }
}
static <T extends Comparable<T>>
T max(T a, T b) {
  return a.compareTo(b) >= 0 ? a : b;
}
max(3, 7);
max("apple", "mango");
JAVA · STREAMS23

Streams & Lambdas

Source
filter
map
sorted
collect

Lazy Evaluation

Intermediate operations like filter and map do not execute until a terminal is called. This enables short-circuiting — findFirst stops scanning the moment it finds a match.

Method References

String double colon toUpperCase is shorthand for s arrow s.toUpperCase. Four forms exist: static method, instance method, constructor, and unbound instance.

Collectors

toList, groupingBy, joining, counting — powerful aggregation operations. Use toUnmodifiableList for defensive defensive-safe return values from methods.

Java 8
List<String> names = List.of(
  "Alice", "Bob", "Anna", "Charlie");
List<String> result = names.stream()
  .filter(n -> n.startsWith("A"))
  .map(String::toUpperCase)
  .sorted()
  .collect(Collectors.toList());
int sum = IntStream.rangeClosed(1, 100)
  .reduce(0, Integer::sum);
var byLetter = names.stream()
  .collect(Collectors.groupingBy(
    n -> n.charAt(0)));
JAVA · EXCEPTIONS24

Java Exceptions

Checked vs Unchecked

Checked — extends Exception — must be caught or declared. Unchecked — extends RuntimeException — optional. Error is a JVM-level problem like OutOfMemoryError — unrecoverable.

try-with-resources

Any AutoCloseable declared in the try parentheses has close called automatically. No finally block needed. Works even if the body throws an exception — no resource leaks.

Multi-catch (Java 7+)

catch (IOException | SQLException e) handles multiple types in one block. DRY and readable. The caught exception is effectively final inside the block.

Custom Exceptions

Extend Exception for checked, RuntimeException for unchecked. Pass context through the super constructor. Modern practice: prefer unchecked for programming errors.

Java
class InsufficientFundsException
    extends RuntimeException {
  InsufficientFundsException(double amt) {
    super("Need $" + amt + " more");
  }
}
try (var br = new BufferedReader(
    new FileReader("data.txt"))) {
  String line = br.readLine();
} catch (IOException | ParseException e) {
  log.error(e.getMessage());
} finally {
  
}
JAVA · NULL SAFETY25

Optional<T>

The Problem — NullPointerException

The billion-dollar mistake. Calling any method on null crashes at runtime with no compile-time warning. Optional makes the absence of a value explicit and forces you to handle it.

Creating Optional

Optional.of throws if you pass null. Optional.ofNullable wraps whatever you give it — null becomes empty. Optional.empty creates an explicitly empty container.

Never call .get() blindly

get throws NoSuchElementException when empty — no better than NPE. Use orElse, orElseGet, orElseThrow, or chain with map and filter instead.

Only for Return Types

Return Optional from methods that might not produce a value. Do not use Optional as a field type, in collections, or as a method parameter — those are anti-patterns.

Java 8
Optional<String> present =
  Optional.of("hello");
Optional<String> empty =
  Optional.empty();
Optional<String> maybe =
  Optional.ofNullable(getName());
String name = maybe
  .map(String::toUpperCase)
  .orElse("UNKNOWN");
maybe.ifPresent(s ->
  System.out.println("Found: " + s));
JAVA · MODERN JAVA26

Records &
Modern Java

Records (Java 16+)

Concise data-carrier classes. One line replaces constructor, getters, equals, hashCode, and toString. Fields are implicitly private and final — naturally immutable.

Sealed Classes (Java 17+)

Restrict which classes can extend or implement a type. The compiler knows all subtypes exhaustively — enables total pattern matching without a default case.

Pattern Matching instanceof

Java 16+. Instead of casting after instanceof, the variable is bound directly: if (obj instanceof String s) then s is already a String inside the block.

Text Blocks (Java 15+)

Multi-line strings with triple-quote syntax. No more escaped newlines and concatenation for JSON, SQL, or HTML literals embedded in Java source.

Java 16+
record Point(int x, int y) {}
var p = new Point(3, 4);
p.x(); p.y();
sealed interface Shape
  permits Circle, Rect {}
record Circle(double r) implements Shape {}
record Rect(double w, double h) implements Shape {}
String txt = """
  { "key": "value",
    "num": 42 }
  """;
OOP · DESIGN PATTERNS27

Common Design Patterns

1⃣

Singleton

Only one instance ever. Private constructor plus static instance getter. Used for configs, logging, connection pools.

Config.getInstance()

Factory

Create objects without specifying exact class. Decouples creation from usage. The caller does not know which subclass it receives.

ShapeFactory.create("circle")

Observer

Objects subscribe to be notified of changes. Event-driven systems, GUI callbacks, reactive streams. Also called Publisher-Subscriber.

bus.subscribe(listener)

Strategy

Swap algorithms at runtime. Define a family of behaviours, encapsulate each, make them interchangeable. Open-closed principle in action.

sorter.setStrategy(new QuickSort())
C++ · STL ALGORITHMS28

STL Algorithms

Searching

find, find_if, count_if, binary_search, lower_bound, upper_bound, equal_range

Sorting

sort, stable_sort, partial_sort, nth_element — all accept lambda comparators

Transforming

transform, for_each, copy, copy_if, fill, replace, remove_if, rotate, reverse

Aggregating

accumulate, reduce, inner_product, min_element, max_element, minmax_element

C++
vector<int> v = {3,1,4,1,5,9};
sort(v.begin(), v.end());
v.erase(
  remove_if(v.begin(), v.end(),
    [](int x){ return x < 3; }),
  v.end());
int total = accumulate(
  v.begin(), v.end(), 0);
for (const auto& x : v)
  cout << x << " ";
COMPARISON29

C++ vs Java

C++
Java
Memory
Manual + RAII smart pointers
Automatic Garbage Collection
Execution
Compiled to native machine code
Bytecode → JVM → JIT
Inheritance
Multiple class inheritance
Single class + unlimited interfaces
Generics
Templates — full code generation
Generics — type erasure
Performance
Highest — zero-cost, no GC pauses
Very good — JIT warms up over time
Best For
OS, games, embedded, browsers, HFT
Enterprise backend, Android, big data
KEY TAKEAWAYS

What You
Now Know

01

C++ gives direct memory control — smart pointers make it safe through RAII, not manual delete calls

02

OOP's four pillars apply to both languages — same concepts, different syntax and enforcement rules

03

STL containers, algorithms, and templates give C++ expressive generic programming with zero overhead

04

Modern C++ — lambdas and move semantics — eliminates most reasons to write manual memory management

05

Java's JVM means write once run anywhere — the GC and JIT handle memory and performance automatically

06

Streams, generics, and interfaces give Java clean expressive architecture for large backend systems

C++
+
Java

NEXT STEPS

Effective C++ — Scott Meyers
Effective Java — Joshua Bloch
LeetCode / HackerRank practice
Build something with each language
C++ · REFERENCES31

C++ References

What is a Reference?

An alias for an existing variable. Cannot be null. Cannot be reseated once bound. Safer and cleaner than raw pointers for everyday use.

Pass by Reference

Avoids copying and lets the function modify the caller's data. Use when you need to mutate an argument or avoid an expensive copy of a large object.

Const Reference — Best Practice

Pass large objects as const T& — no copy, no modification. The cheapest and safest way to pass read-only data into a function.

Reference in Range-For

for (const auto& item : vec) iterates without copying each element. Without the & you get a full copy on every iteration — expensive for strings and large objects.

C++
int x = 42;
int& ref = x;
ref = 100;
void increment(int& n) { ++n; }
increment(x);
void print(const string& s) {
  cout << s;
}
vector<string> names = {"Alice", "Bob"};
for (const auto& n : names)
  cout << n;
for (auto& n : names)
  n += "!";
C++ · OPERATOR OVERLOADING32

Operator Overloading

What and Why

Define what operators like +, ==, << mean for custom types. Makes mathematical and container types read naturally.

Member vs Free Function

Symmetric operators like + and == are often free functions. Unary operators and assignment operators are typically members.

operator<< for Streams

Lets you write cout << myObj. Must be a free function taking ostream& and returning ostream& to support chaining.

Java Has None of This

Java deliberately excludes operator overloading. The only exception is + for String concatenation — baked into the compiler, not user-definable.

C++
struct Vec2 {
  double x, y;
  Vec2 operator+(const Vec2& o) const {
    return {x+o.x, y+o.y};
  }
  bool operator==(const Vec2& o) const {
    return x==o.x && y==o.y;
  }
};
ostream& operator<<(ostream& os, const Vec2& v) {
  return os << "(" << v.x << "," << v.y << ")";
}
Vec2 a{1,2}, b{3,4};
Vec2 c = a + b;
cout << c;
JAVA · FUNCTIONAL INTERFACES33

Functional
Interfaces

What Makes an Interface Functional?

Exactly one abstract method. The @FunctionalInterface annotation enforces this at compile time. Enables lambdas and method references anywhere the interface is expected.

Predicate<T>

Takes a T, returns boolean. Used in stream.filter(). Example: Predicate<String> isLong = s -> s.length() > 5

Function<T, R>

Takes a T, returns an R. Used in stream.map(). Example: Function<String, Integer> len = String::length

Consumer<T> and Supplier<T>

Consumer takes T, returns nothing — used in forEach. Supplier takes nothing, returns T — used for lazy evaluation and factory patterns.

Java 8
@FunctionalInterface
interface Transformer<T, R> {
  R transform(T input);
}
Predicate<String> isLong = s -> s.length() > 5;
Function<String, Integer> len = String::length;
Consumer<String> print = System.out::println;
Supplier<List> newList = ArrayList::new;
List<String> words = List.of("hi", "hello", "hey");
words.stream()
  .filter(isLong)
  .map(len)
  .forEach(print);
JAVA · CONCURRENCY34

Java Concurrency
Basics

Race Condition — The Core Problem

Two threads read-modify-write the same variable simultaneously. The result is unpredictable. Classic case: two threads both incrementing a counter, losing one increment.

synchronized — The Basic Lock

Only one thread enters the block at a time. Solves race conditions but can cause bottlenecks. Coarse-grained — use only when necessary.

AtomicInteger — Lock-Free

Uses CPU compare-and-swap hardware instructions. Thread-safe, faster than synchronized for single-variable operations. Part of java.util.concurrent.atomic.

CompletableFuture — Async Composition

Chain async operations without blocking. thenApply, thenCombine, exceptionally. The modern way to write non-blocking backend code.

Java
AtomicInteger count = new AtomicInteger(0);
count.incrementAndGet();
synchronized void safeIncrement() {
  counter++;
}
var exec = Executors.newFixedThreadPool(4);
Future<Integer> f = exec.submit(() -> compute());
int result = f.get();
CompletableFuture
  .supplyAsync(() -> fetchData())
  .thenApply(data -> process(data))
  .thenAccept(System.out::println)
  .exceptionally(e -> { log(e); return null; });
C++ · MODERN C++1735

Modern C++
Features

auto — Type Inference

Compiler infers the type from the initializer. Not dynamic typing — the type is compile-time fixed, just not written redundantly. Reduces verbosity significantly.

Range-Based For

for (const auto& x : container) replaces begin/end iterator loops. Cleaner, less error-prone, works with any type that provides begin and end.

Structured Bindings (C++17)

Unpack pairs and tuples directly: auto [key, val] = entry. Much cleaner than accessing .first and .second repeatedly.

std::optional (C++17)

A value that may or may not be present. No null pointers, no sentinel values. Check with has_value(), get with value_or(default).

C++17
auto x = 42;
auto name = string("hello");
map<string, int> scores;
for (const auto& [name, score] : scores) {
  cout << name << ": " << score;
}
auto pair = make_pair("Alice", 95);
auto [student, grade] = pair;
optional<int> findScore(string name);
auto result = findScore("Alice");
int s = result.value_or(0);
OOP · SOLID PRINCIPLES36

SOLID Design Principles

S — Single Responsibility

A class should have one reason to change. User class handles user data — not email sending, not DB access. Split concerns into separate classes.

O — Open / Closed

Open for extension, closed for modification. Add new behaviour through subclassing or composition — do not edit working code to add features.

L — Liskov Substitution

A derived class must be substitutable for its base. If Square extends Rectangle and breaks setWidth, that violates Liskov — do not override to weaken guarantees.

I — Interface Segregation

Many small focused interfaces beat one large general one. Clients should not depend on methods they do not use. Keep interfaces lean.

D — Dependency Inversion

Depend on abstractions, not concretions. Inject dependencies rather than creating them inside a class. Enables testing with mock objects.

C++ + JAVA · BUILD TOOLS37

Build Systems

C++ — CMake

The modern cross-platform build system. Generates Makefiles, Ninja files, or IDE projects. CMakeLists.txt describes targets, sources, and dependencies. Industry standard for new C++ projects.

C++ — Make

The classic Unix build tool. A Makefile defines rules: how to compile each file and link the final binary. Still widely used, especially on Linux. CMake often generates Makefiles.

Java — Maven

XML-based build and dependency manager. pom.xml declares dependencies from Maven Central repository. Downloads and manages JARs automatically. The long-time industry standard.

Java — Gradle

Groovy or Kotlin DSL build tool. Faster than Maven with incremental builds. Default for Android. Increasingly common in new Java projects. More flexible, less verbose than Maven.

CMake + Maven
cmake_minimum_required(VERSION 3.20)
project(MyApp)
add_executable(app main.cpp)
target_link_libraries(app PRIVATE fmt)
<dependency>
  <groupId>com.google.guava</groupId>
  <artifactId>guava</artifactId>
  <version>32.0.0-jre</version>
</dependency>
dependencies {
  implementation('com.google.guava:guava:32.0.0-jre')
}
INTERACTIVE · SLIDES 39 – 41

Activities

Quiz  ·  Concept Match  ·  Language Classifier

8 questions8 pairs12 concepts
Play
ACTIVITY 01 · QUICK FIRE QUIZ39

Quick Fire Quiz

8 questions  ·  test your C++ and Java knowledge

ACTIVITY 02 · CONCEPT MATCH40

Concept Match

Click a term, then click its matching definition  ·  Find all 8 pairs

ACTIVITY 03 · LANGUAGE CLASSIFIER41

Sort It Out

Click a concept to select it, then click a zone to assign it  ·  Classify all 12