Java Streams become even more powerful when combined with Optional and file handling APIs. In this article, we’ll explore how to safely handle missing values using Optional, process files efficiently with Files.lines(), and build a practical example that counts unique words in a text file.
If you’ve followed the earlier parts of this series, you already know how Streams help process collections in a functional and readable way. Now it’s time to apply those concepts to real-world scenarios.
Why Combine Streams, Optional, and File I/O?
In modern Java applications, you often:
- Read large files
- Process textual data
- Search for values that may or may not exist
- Avoid
NullPointerException - Write concise and clean code
Streams, Optional, and Java NIO APIs work together beautifully to solve these problems.
Using Optional with Streams
Optional<T> is a container object introduced in Java 8 that may or may not contain a value.
Streams often return Optional when the result may be absent.
Common Stream Methods Returning Optional
| Method | Return Type |
|---|---|
findFirst() |
Optional<T> |
findAny() |
Optional<T> |
max() |
Optional<T> |
min() |
Optional<T> |
reduce() |
Optional<T> |
Example: findFirst()
import java.util.List;
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
List<String> names = List.of("Aman", "Priyank", "Rahul");
Optional<String> result = names.stream()
.filter(name -> name.startsWith("P"))
.findFirst();
result.ifPresent(System.out::println);
}
}
Output:
Priyank
Handling Empty Results Safely
Without Optional, missing values could lead to NullPointerException.
Using orElse()
String value = result.orElse("Not Found");
System.out.println(value);
If no matching element exists, "Not Found" is returned.
Using orElseGet()
String value = result.orElseGet(() -> "Default Value");
Useful when default value creation is expensive.
Using orElseThrow()
String value = result.orElseThrow(
() -> new RuntimeException("Value not found")
);
Throws an exception if value is absent.
Example: Find Maximum Number
import java.util.List;
import java.util.Optional;
public class MaxExample {
public static void main(String[] args) {
List<Integer> numbers = List.of(10, 20, 50, 30);
Optional<Integer> max = numbers.stream()
.max(Integer::compareTo);
max.ifPresent(System.out::println);
}
}
Output
50
Here, numbers.stream().max() returns an Optional. ifPresent() is another inbuilt function on Optional<T> type value which perform an action (in this case printing the value to console) if some value is returned by the stream.
Reading Files Using Files.lines()
Java NIO introduced the Files.lines() method for efficient file reading.
Instead of loading the entire file into memory, it processes the file lazily line by line using Streams.
Syntax
Files.lines(Path path)
Returns Stream<String>. Each line of the file becomes a stream element.
Basic Example
Suppose sample.txt contains:
Java
Spring Boot
Streams API
import java.nio.file.Files;
import java.nio.file.Paths;
public class FileReadExample {
public static void main(String[] args) {
try {
Files.lines(Paths.get("sample.txt"))
.forEach(System.out::println);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Output
Java
Spring Boot
Streams API
Why Files.lines() is Powerful
- Memory efficient
- Lazy processing
- Works well with large files
- Can directly use Stream operations
Example: Filter Lines
Files.lines(Paths.get("sample.txt"))
.filter(line -> line.contains("Java"))
.forEach(System.out::println);
Example: Count Lines
long count = Files.lines(Paths.get("sample.txt"))
.count();
System.out.println(count);
Real-World Example: Count Unique Words in a Text File
Now let’s combine everything we learned.
We will:
- Read a text file
- Split lines into words
- Convert words to lowercase
- Remove duplicates
- Count unique words
Sample file (article.txt)
Java Streams are powerful
Streams make Java code concise
Java is widely used
Program
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;
public class UniqueWordCounter {
public static void main(String[] args) {
try (Stream<String> lines = Files.lines(Paths.get("article.txt"))){ // Read File as Stream
long uniqueWords = lines
.flatMap(line -> Stream.of(line.split("\\s+"))) // Convert Lines into Words
.map(String::toLowerCase) // convert the words to lowercase
.distinct() // remove duplicates
.count(); // count unique words
System.out.println("Unique Words: " + uniqueWords);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Output
Unique Words: 10
Another Example: Find First Long Word (word with more than 7 characters) Using Optional
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Optional;
import java.util.stream.Stream;
public class LongWordFinder {
public static void main(String[] args) {
try (Stream<String> lines = Files.lines(Paths.get("article.txt"))) {
Optional<String> word = lines
.flatMap(line -> Stream.of(line.split("\\s+")))
.filter(w -> w.length() > 7) // filter the words with length greater than 7 characters
.findFirst(); // pick the first word among the filtered long words
System.out.println(
word.orElse("No long word found")
);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Best Practices
Always Use try-with-resources. Files.lines() opens a file resource. Always close it properly:
try (Stream<String> lines = Files.lines(path)) {
// process
}
Prefer Stream Operations Over Manual Loops
Instead of:
for(String line : lines)
Use:
lines.filter(...)
.map(...)
Cleaner and more functional.
Avoid Calling get() on Optional Directly
Bad:
optional.get();
Safer alternatives:
orElse()
orElseThrow()
ifPresent()
Conclusion
Streams are not limited to collections. When combined with Optional and Java NIO file APIs, they become a powerful toolkit for handling real-world data processing tasks efficiently and elegantly.
In this article, we learned how to:
- Use
Optionalsafely with Streams - Read files using
Files.lines() - Process text data functionally
- Count unique words in a file
These techniques are commonly used in backend systems, analytics tools, log processing applications, and Java projects.
Top comments (0)