C
JV

C to Java

10 lessons

Progress0%
1Introduction to Java2Data Types3Strings4Arrays and Collections5Object-Oriented Programming6Exception Handling7Collections and Generics8Modern Java Features9Interfaces and Polymorphism10Threads and Concurrency
All Mirror Courses
C
JV
Modern Java Features
MirrorLesson 8 of 10
Lesson 8

Modern Java Features

Stream API, lambdas, Optional, var, records — Java 8-21 features

Introduction

In this lesson, you'll learn about modern java features in Java. Coming from C, you already have a foundation for understanding this concept. We'll build on that knowledge while highlighting the key differences.

Mirror Card
C
From C:

In C, you're familiar with stream api, lambdas, optional, var, records — java 8-21 features.

JV
In Java:

Java has its own approach to stream api, lambdas, optional, var, records — java 8-21 features, which we'll explore step by step.

The Java Way

Let's see how Java handles this concept. Here's a typical example:

JV
Java Example
import java.util.*;
import java.util.stream.*;

// Stream API + lambdas (Java 8+)
List<Integer> nums = List.of(1,2,3,4,5,6);

int sum = nums.stream()
    .filter(x -> x % 2 == 0)     // lambda replaces function pointer
    .mapToInt(Integer::intValue)  // method reference
    .sum();
// sum = 12

// Collect to list
List<Integer> evens = nums.stream()
    .filter(x -> x % 2 == 0)
    .collect(Collectors.toList());

// Optional<T> — explicit nullable (vs C's -1 sentinel)
Optional<Integer> first = nums.stream()
    .filter(x -> x > 3)
    .findFirst();                          // Optional[4]
first.ifPresent(v -> System.out.println("Found: " + v));
int val = first.orElse(-1);               // -1 if absent

// var — local type inference (Java 10+)
var map = new HashMap<String, List<Integer>>();

// Records (Java 16+) — immutable data classes
record Point(double x, double y) {}
var p = new Point(1.0, 2.0);
System.out.println(p);  // Point[x=1.0, y=2.0]
System.out.println(p.x()); // getter

// Text blocks (Java 15+)
String json = """
    {"name": "Alice", "age": 30}
    """;

Comparing to C

Here's how you might have written similar code in C:

C
C (What you know)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// Manual loop for filtering
int evens[100], count = 0;
int nums[] = {1,2,3,4,5,6};
int n = 6;
for (int i = 0; i < n; i++)
    if (nums[i] % 2 == 0) evens[count++] = nums[i];

// Manual sum
int sum = 0;
for (int i = 0; i < count; i++) sum += evens[i];

// No lambdas — use function pointers
typedef int (*Predicate)(int);
int isEven(int x) { return x % 2 == 0; }

// Optional-like: return -1 for "not found"
int findFirst(int *arr, int n, Predicate pred) {
    for (int i = 0; i < n; i++)
        if (pred(arr[i])) return arr[i];
    return -1; // "not found"
}
Mirror Card
C
From C:

You may be used to different syntax or behavior.

JV
In Java:

Stream API replaces manual for loops with declarative filter/map/reduce pipelines

Mirror Card
C
From C:

You may be used to different syntax or behavior.

JV
In Java:

Lambdas (x -> expr) replace function pointers — more concise, type-safe

Mirror Card
C
From C:

You may be used to different syntax or behavior.

JV
In Java:

Optional<T> replaces sentinel values (-1, null) for absent results

Mirror Card
C
From C:

You may be used to different syntax or behavior.

JV
In Java:

var enables type inference for local variables — reduces verbosity

Mirror Card
C
From C:

You may be used to different syntax or behavior.

JV
In Java:

Records replace data-only classes — auto-generate constructor, getters, equals, toString

Step-by-Step Breakdown

1. Streams and Lambdas

Streams are lazy pipelines on collections. Lambdas (x -> expr) are inline function definitions — cleaner than C's function pointers.

C
C
// C: manual loop with function pointer
for(int i=0;i<n;i++) if(pred(arr[i])) process(arr[i]);
JV
Java
list.stream()
    .filter(x -> x % 2 == 0)   // lambda
    .map(x -> x * x)            // lambda
    .forEach(System.out::println); // method ref

2. Optional

Optional<T> makes the possibility of absence explicit in the API. Better than -1 sentinels or null returns.

C
C
// C: -1 or NULL means "not found"
int result = findFirst(arr, n, isEven);
if (result != -1) use(result);
JV
Java
Optional<Integer> result = list.stream()
    .filter(x -> x % 2 == 0)
    .findFirst();
result.ifPresent(v -> use(v));
int v = result.orElse(0);

3. Records

Records declare immutable data classes in one line. Auto-generated: compact constructor, accessors (name()), equals, hashCode, toString.

C
C
typedef struct { double x, y; } Point;
// No equals, toString, hashCode
JV
Java
record Point(double x, double y) {}
var p = new Point(1.0, 2.0);
p.x();              // getter — no getX()
p.equals(new Point(1.0, 2.0)); // true
System.out.println(p); // Point[x=1.0, y=2.0]

4. var and Text Blocks

var infers the type from the right-hand side. Text blocks (triple-quoted strings) replace messy string concatenation for multi-line strings.

C
C
// C: must always specify type
HashMap<String, Integer> map = new HashMap<>();
char *json = "{\"name\": \"Alice\"}";  // escaped mess
JV
Java
var map = new HashMap<String, Integer>(); // inferred
String json = """
    {"name": "Alice"}
    """;  // no escaping needed

Common Mistakes

When coming from C, developers often make these mistakes:

  • Stream API replaces manual for loops with declarative filter/map/reduce pipelines
  • Lambdas (x -> expr) replace function pointers — more concise, type-safe
  • Optional<T> replaces sentinel values (-1, null) for absent results
Common Pitfall
Don't assume Java works exactly like C. While the concepts may be similar, the syntax and behavior can differ significantly.

Key Takeaways

  • Stream API: filter/map/reduce replace manual loops; lambdas replace function pointers
  • Optional<T> replaces sentinel values (null, -1) for explicitly-absent results
  • Records: one-line immutable data class with auto-generated constructor/getters/equals/toString
  • var: local type inference; text blocks: multi-line strings without escaping
Rule of Thumb
The best way to learn is by doing. Try rewriting some of your C code in Java to practice these concepts.
PreviousNext