dtonhofer

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 Top

abtin
page 20: … protoc command… I had to additionally run the following go get commands in order to be able to compile protobuf code using go...
New
jimschubert
In Chapter 3, the source for index introduces Config on page 31, followed by more code including tests; Config isn’t introduced until pag...
New
HarryDeveloper
Hi @venkats, It has been mentioned in the description of ‘Supervisory Job’ title that 2 things as mentioned below result in the same eff...
New
joepstender
The generated iex result below should list products instead of product for the metadata. (page 67) iex&gt; product = %Product{} %Pento....
New
leba0495
Hello! Thanks for the great book. I was attempting the Trie (chap 17) exercises and for number 4 the solution provided for the autocorre...
New
jonmac
The allprojects block listed on page 245 produces the following error when syncing gradle: “org.gradle.api.GradleScriptException: A prob...
New
gorkaio
root_layout: {PentoWeb.LayoutView, :root}, This results in the following following error: no “root” html template defined for PentoWeb...
New
dachristenson
I just bought this book to learn about Android development, and I’m already running into a major issue in Ch. 1, p. 20: “Update activity...
New
roadbike
From page 13: On Python 3.7, you can install the libraries with pip by running these commands inside a Python venv using Visual Studio ...
New
dachristenson
I’ve got to the end of Ch. 11, and the app runs, with all tabs displaying what they should – at first. After switching around between St...
New

Other popular topics Top

AstonJ
SpaceVim seems to be gaining in features and popularity and I just wondered how it compares with SpaceMacs in 2020 - anyone have any thou...
New
AstonJ
This looks like a stunning keycap set :orange_heart: A LEGENDARY KEYBOARD LIVES ON When you bought an Apple Macintosh computer in the e...
New
PragmaticBookshelf
“Finding the Boundaries” Hero’s Journey with Noel Rappin @noelrappin Even when you’re ultimately right about what the future ho...
New
DevotionGeo
The V Programming Language Simple language for building maintainable programs V is already mentioned couple of times in the forum, but I...
New
AstonJ
Biggest jackpot ever apparently! :upside_down_face: I don’t (usually) gamble/play the lottery, but working on a program to predict the...
New
Maartz
Hi folks, I don’t know if I saw this here but, here’s a new programming language, called Roc Reminds me a bit of Elm and thus Haskell. ...
New
PragmaticBookshelf
Build efficient applications that exploit the unique benefits of a pure functional language, learning from an engineer who uses Haskell t...
New
Help
I am trying to crate a game for the Nintendo switch, I wanted to use Java as I am comfortable with that programming language. Can you use...
New
New
DevotionGeo
I have always used antique keyboards like Cherry MX 1800 or Cherry MX 8100 and almost always have modified the switches in some way, like...
New

Latest in Functional Programming in Java, Second Edition

Functional Programming in Java, Second Edition Portal

Sub Categories: