Register

Java for Beginners

0 of 24 notes read 0%

Reading progress is saved to your INFIRALS account. Sign in to keep this note marked as read.

Lambdas, streams, and files

Exceptions, collections and modern Java13 min readLesson 6 of 6

6.1 Lambdas

A lambda is a short implementation of a functional interface. (a, b) -> a + b gives the parameters and the result. The compiler uses the target type to find the parameter types and the method it implements.

Runnable task = () -> System.out.println("Done"); implements run. A lambda with one expression can omit braces; a block uses braces and an explicit return when a value is needed.

A method reference is shorter when an existing method does the work: String::toUpperCase in place of text -> text.toUpperCase(). Use it when the lambda would only pass its arguments through.

java
import java.util.ArrayList;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        Runnable task = () -> System.out.println("Task done");
        task.run();
        List<String> names = new ArrayList<>(List.of("Ravi", "Asha"));
        names.sort((a, b) -> a.compareTo(b));
        System.out.println(names);
    }
}

Output

Task done
[Asha, Ravi]

6.1.1 Stream pipelines

A stream processes a collection as a pipeline. stream() starts it, filter keeps matching elements, map transforms each one, and a terminal operation such as count, toList, or collect produces a result.

Intermediate operations are lazy. Nothing runs until a terminal operation asks for a result. That allows the implementation to combine steps and skip work.

A stream does not change the source collection. It reads from it and produces a new result. Reusing a stream after a terminal operation throws IllegalStateException; create a new stream from the source.

java
import java.util.List;

public class Main {
    public static void main(String[] args) {
        List<Integer> marks = List.of(45, 72, 88, 61, 90);
        long passed = marks.stream()
                .filter(mark -> mark >= 60)
                .count();
        List<Integer> top = marks.stream()
                .filter(mark -> mark >= 60)
                .map(mark -> mark + 5)
                .limit(2)
                .toList();
        System.out.println(passed);
        System.out.println(top);
    }
}

Output

4
[77, 93]

6.1.2 Collecting results

toList() collects the elements into an unmodifiable list. collect is the general form and also accepts collectors such as Collectors.joining(", "), which builds a string from text elements.

mapToInt converts objects to primitive ints and provides sum, average, and max. These avoid boxing each value and return an IntStream with numeric operations.

Keep a pipeline short enough to read in one pass. If the logic needs names and branches, a loop may be clearer. Streams help most when each step transforms the collection in a clear way.

java
import java.util.List;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<String> names = List.of("Asha", "Ravi", "Meera");
        String line = names.stream()
                .filter(name -> name.length() > 3)
                .map(String::toUpperCase)
                .collect(Collectors.joining(", "));
        System.out.println(line);
        System.out.println(names.stream().mapToInt(String::length).sum());
    }
}

Output

ASHA, RAVI, MEERA
13

6.1.3 Files with java.nio

Files.writeString(path, text) writes text to a file, creating or replacing it. Files.readString(path) reads the whole file into a String. Both are in java.nio.file and both can throw IOException.

Path.of("notes.txt") creates a path object for a relative file in the working directory. The methods take a Path object, so a file name string needs Path.of(...) first.

For large files, read line by line or use Files.lines(path) as a stream. For a short configuration file or a small note, reading the whole text is simpler.

java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

public class Main {
    public static void main(String[] args) throws IOException {
        Path file = Path.of("notes.txt");
        Files.writeString(file, "line one\nline two");
        String content = Files.readString(file);
        System.out.println(content.lines().count());
        System.out.println(content.toUpperCase());
    }
}

Output

2
LINE ONE
LINE TWO

6.1.4 Resources and exceptions

File operations throw checked exceptions. A method can declare throws IOException and let the caller handle it, or catch it and report a useful message. The declaration is often enough in a small example; a larger program needs a decision about retry, fallback, or exit.

Files.lines(path) returns a stream that holds an open file. Use try-with-resources so the file closes when the stream finishes. Files.readAllLines returns a list and closes the file for you.

A path can point outside the working directory. Validate user-supplied paths before opening them, especially in a program that runs with access to a real file system.

java
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

public class Main {
    public static void main(String[] args) throws IOException {
        Path file = Path.of("tasks.txt");
        Files.write(file, List.of("read", "practice", "review"));
        List<String> lines = Files.readAllLines(file);
        for (String line : lines) {
            System.out.println(line.toUpperCase());
        }
    }
}

Output

READ
PRACTICE
REVIEW

6.1.5 Practice

  1. Sort a mutable list of names with a lambda comparator.
  2. Filter marks above 60, add 5 to each, and collect the first two into a list.
  3. Join names longer than four characters with ", " and print the result.
  4. Write two lines to a file and read them back with Files.readString.
  5. Write a list of tasks to a file, read all lines, and print each in uppercase.

For step 4, print the line count with content.lines().count(). The count should match the number of lines you wrote, with no final empty line.

Interview questions

3 questions from this note. Open one to see the answer; no account needed.

  • 01What is a lambda expression?

    A short implementation of a functional interface. The target type supplies the method signature, so the lambda only writes the parameters and body.

  • 02When does a stream pipeline run?

    Intermediate operations are lazy. The work happens when a terminal operation such as `count`, `toList`, or `collect` is called.

  • 03Why use try-with-resources with `Files.lines`?

    The stream keeps the file open. Try-with-resources closes it when the block ends, including when an exception occurs.