 
  		        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
                         
                      
                       
          
                Hi Brian, 
Looks like the api for tinydb has changed a little. Noticed while working on chapter 7 that the .purge() call to the db throws...
              
            
            
          
              New
 
          
                When I try the command to create a pair of migration files I get an error. 
user=> (create-migration "guestbook")
Execution error (Ill...
              
            
            
          
              New
 
          
                I can’t setup the Rails source code. This happens in a working directory containing multiple (postgres) Rails apps. 
With: 
ruby-3.0.0 
s...
              
            
            
          
              New
 
          
                #book-python-testing-with-pytest-second-edition 
Hi. Thanks for writing the book. I am just learning so this might just of been an issue ...
              
            
            
          
              New
 
          
                I’m under the impression that when the reader gets to page 136 (“View Data with the Database Inspector”), the code SHOULD be able to buil...
              
            
            
          
              New
 
          
                I’m not quite sure what’s going on here, but I’m unable to have to containers successfully complete the Readiness/Liveness checks. I’m im...
              
            
            
          
              New
 
          
                Title: Build a Weather Station with Elixir and Nerves: Problem connecting to Postgres with Grafana on  (page 64) 
If you follow the defau...
              
            
            
          
              New
 
          
                On page 78 the following code appears: 
<%= link_to ‘Destroy’, product, 
class: ‘hover:underline’, 
method: :delete, 
data: { confirm...
              
            
            
          
              New
 
          
                It seems the second code snippet is missing the code to set the current_user: 
current_user: Accounts.get_user_by_session_token(session["...
              
            
            
          
              New
 
          
                Hello faithful readers!  If you have tried to follow along in the book, you are asked to start up the dev environment via dx/build and ar...
              
            
            
          
              New
Other popular topics
                         
                      
                       
          
                Algorithms and data structures are much more than abstract concepts. Mastering them enables you to write code that runs faster and more e...
              
            
            
              
          
              New
 
          
                I’m thinking of buying a monitor that I can rotate to use as a vertical monitor? 
Also, I want to know if someone is using it for program...
              
            
            
          
              New
 
          
                Curious to know which languages and frameworks you’re all thinking about learning next :upside_down_face: 
Perhaps if there’s enough peop...
              
            
            
          
              New
 
          
                Thanks to @foxtrottwist’s and @Tomas’s posts in this thread: Poll: Which code editor do you use? I bought Onivim! :nerd_face: 
https://on...
              
            
            
          
              New
 
          
                Biggest jackpot ever apparently! :upside_down_face: 
I don’t (usually) gamble/play the lottery, but working on a program to predict the...
              
            
            
          
              New
 
          
                A few weeks ago I started using Warp a terminal written in rust. Though in it’s current state of development there are a few caveats (tab...
              
            
            
          
              New
 
          
                This is going to be a long an frequently posted thread. 
While talking to a friend of mine who has taken data structure and algorithm cou...
              
            
            
          
              New
 
          
                Rails 7 completely redefines what it means to produce fantastic user experiences and provides a way to achieve all the benefits of single...
              
            
            
              
          
              New
 
          
                There appears to have been an update that has changed the terminology for what has previously been known as the Taskbar Overflow - this h...
              
            
            
          
              New
 
          
                Big O Notation can make your code faster by orders of magnitude. Get the hands-on info you need to master data structures and algorithms ...
              
            
            
              
          
              New
Categories:
Sub Categories:
Popular Portals
- /elixir
- /rust
- /ruby
- /wasm
- /erlang
- /phoenix
- /keyboards
- /python
- /rails
- /js
- /security
- /go
- /swift
- /vim
- /clojure
- /haskell
- /emacs
- /java
- /svelte
- /onivim
- /typescript
- /kotlin
- /c-plus-plus
- /crystal
- /tailwind
- /react
- /gleam
- /ocaml
- /elm
- /flutter
- /vscode
- /ash
- /html
- /opensuse
- /centos
- /php
- /zig
- /deepseek
- /scala
- /lisp
- /textmate
- /sublime-text
- /react-native
- /nixos
- /debian
- /agda
- /kubuntu
- /arch-linux
- /django
- /revery
- /deno
- /ubuntu
- /spring
- /nodejs
- /manjaro
- /diversity
- /lua
- /julia
- /slackware
- /c
 
    





