dtonhofer
Functional Programming in Java, Second Edition: Functional Programming in Java, Second Edition: JUnit code improvements for Chapter 11, pages 192 ff “Refactoring File Processing”
In this code:
- We actually create the (temporary) file we want to read and delete it again at the end.
- Default charsets for reading text files are the work of the devil, we set UTF-8 explicitly.
- The files need to be properly closed with try-with-resources, this also applies to the stream approach.
- A “long” count as return value seems excessive, dropping to int.
package chapter11;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class FileProcessingTest {
private static File actualFile;
private final static Charset charset = StandardCharsets.UTF_8;
// Creates a file "/tmp/WordCount13982583023783245787.java" for example
@BeforeAll
static void createTmpFile() throws IOException {
actualFile = File.createTempFile("WordCount", ".java");
try (FileWriter writer = new FileWriter(actualFile, charset)) {
writer.write("package foo;\n");
writer.write("public class X {\n");
writer.write("}\n");
writer.write("public class Y {\n");
writer.write("}\n");
}
}
@AfterAll
static void deleteTmpFile() throws IOException {
// or one could have installed a handler with deleteOnExit()
actualFile.delete();
}
interface WordCount {
int countInFile(String word, File file) throws IOException;
}
// https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/io/FileReader.html
// https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/io/BufferedReader.html
static class WordCountBefore implements WordCount {
public int countInFile(final String searchWord, final File file) throws IOException {
int count = 0;
// Use try-with-resources / automatic resource management to clean up.
// Specify the charset, "default chartset" is the devil's work!
try (final var bufferedReader = new BufferedReader(new FileReader(file, charset))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
final String[] words = line.split(" ");
for (String word : words) {
if (word.equals(searchWord)) {
count++;
}
}
}
return count;
}
}
}
// https://docs.oracle.com/en/java/javase/18/docs/api/java.base/java/nio/file/Files.html
static class WordCountAfter implements WordCount {
// The Files.lines() call may throw IOException.
// Additionally, the count() this yields a "long", so we need to cast to fit the interface.
// We still must use try-with-resources to close the file.
public int countInFile(final String searchWord, final File file) throws IOException {
try (final Stream<String> stream = Files.lines(file.toPath(), charset)) {
return (int) stream
.flatMap(line -> Stream.of(line.split(" ")))
.filter(word -> word.equals(searchWord))
.count();
}
}
}
private static void commonFileProcessingTests(final WordCount wordCount, File file) {
assertAll(
() -> assertEquals(2, wordCount.countInFile("public", file)),
() -> assertEquals(1, wordCount.countInFile("package", file)));
}
@Test
void fileProcessingBefore() {
commonFileProcessingTests(new WordCountBefore(), actualFile);
}
@Test
void fileProcessingAfter() {
commonFileProcessingTests(new WordCountAfter(), actualFile);
}
}
Popular Pragmatic Bookshelf topics
Working through the steps (checking that the Info,plist matches exactly), run the demo game and what appears is grey but does not fill th...
New
Title: Hands-On Rust (Chap 8 (Adding a Heads Up Display)
It looks like
.with_simple_console_no_bg(SCREEN_WIDTH*2, SCREEN_HEIGHT*2...
New
Page 28: It implements io.ReaderAt on the store type.
Sorry if it’s a dumb question but was the io.ReaderAt supposed to be io.ReadAt?
...
New
I’m running Android Studio “Arctic Fox” 2020.3.1 Patch 2, and I’m embarrassed to admit that I only made it to page 8 before running into ...
New
This is as much a suggestion as a question, as a note for others.
Locally the SGP30 wasn’t available, so I ordered a SGP40. On page 53, ...
New
Hi, I have just acquired Michael Fazio’s “Kotlin and Android Development” to learn about game programming for Android. I have a game in p...
New
When I run the coverage example to report on missing lines, I get:
pytest --cov=cards --report=term-missing ch7
ERROR: usage: pytest [op...
New
Modern front-end development for Rails, second edition - Struggling to get the first chapter to work
After running /bin/setup, the first error was: The foreman' command exists in these Ruby versions: That was easy to fix: gem install fore...
New
When running the program in chapter 8, “Implementing Combat”, the printout Health before attack was never printed so I assumed something ...
New
@mfazio23
I’ve applied the changes from Chapter 5 of the book and everything builds correctly and runs. But, when I try to start a game,...
New
Other popular topics
Please tell us what is your preferred monitor setup for programming(not gaming) and why you have chosen it.
Does your monitor have eye p...
New
New
Small essay with thoughts on macOS vs. Linux:
I know @Exadra37 is just waiting around the corner to scream at me “I TOLD YOU SO!!!” but I...
New
If you are experiencing Rails console using 100% CPU on your dev machine, then updating your development and test gems might fix the issu...
New
Learn different ways of writing concurrent code in Elixir and increase your application's performance, without sacrificing scalability or...
New
Crystal recently reached version 1. I had been following it for awhile but never got to really learn it. Most languages I picked up out o...
New
Author Spotlight:
VM Brasseur
@vmbrasseur
We have a treat for you today! We turn the spotlight onto Open Source as we sit down with V...
New
zig/http.zig at 7cf2cbb33ef34c1d211135f56d30fe23b6cacd42 · ziglang/zig.
General-purpose programming language and toolchain for maintaini...
New
Develop, deploy, and debug BEAM applications using BEAMOps: a new paradigm that focuses on scalability, fault tolerance, and owning each ...
New
Background
Lately I am in a quest to find a good quality TTS ai generation tool to run locally in order to create audio for some videos I...
New
Categories:
Sub Categories:
Popular Portals
- /elixir
- /rust
- /ruby
- /wasm
- /erlang
- /phoenix
- /keyboards
- /python
- /js
- /rails
- /security
- /go
- /swift
- /vim
- /clojure
- /emacs
- /haskell
- /java
- /svelte
- /onivim
- /typescript
- /kotlin
- /c-plus-plus
- /crystal
- /tailwind
- /react
- /gleam
- /ocaml
- /flutter
- /elm
- /vscode
- /ash
- /html
- /opensuse
- /centos
- /zig
- /deepseek
- /php
- /scala
- /react-native
- /lisp
- /textmate
- /sublime-text
- /debian
- /nixos
- /agda
- /django
- /kubuntu
- /arch-linux
- /deno
- /ubuntu
- /revery
- /nodejs
- /spring
- /manjaro
- /lua
- /diversity
- /julia
- /markdown
- /slackware








