dtonhofer
Functional Programming in Java, Second Edition: Functional Programming in Java, Second Edition: JUnit code improvements for Chapter 11, pages 189 ff “Refactoring to Rework the Logic”
The usual changes but:
- The “FirstRepeatedLetter.findIn()” has been improved out of the box. In particular returning ‘\0’ is too C-like and smells like “primitive obsession”. We have
null, we should use it. What if the input contains\0as the matching character? - A slightly better code (IMHO) is in
FirstRepeatedLetterBetter.findIn() - The final refactored code returns not null, but
Optional<Character>, which is cleaner. - Again, for testing we use a common interface or a wrapper class to avoid having to duplicate testing code.
package chapter11;
import org.junit.jupiter.api.Test;
import java.util.Optional;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.*;
public class ReworkTheLogicTest {
interface FindLetter {
Character findIn(String word);
}
static class FirstRepeatedLetterBefore implements FindLetter {
public Character findIn(final String word) {
final char[] letters = word.toCharArray();
for (char candidate : letters) {
int count = 0;
for (char letter : letters) {
if (candidate == letter) {
count++;
}
}
if (count > 1) {
return candidate;
}
}
return null;
}
}
static class FirstRepeatedLetterBetter implements FindLetter {
public Character findIn(final String word) {
char[] letters = word.toCharArray();
int i = 0;
Character found = null;
while (i < letters.length && found == null) {
// will letter[i] been seen again?
char maybe = letters[i];
int j = i + 1;
while (j < letters.length && letters[j] != maybe) j++;
if (j < letters.length) {
found = maybe;
} else {
i++;
}
}
return found;
}
}
// Does NOT implement "FindLetter", returns Optional<Character>
static class FirstRepeatedLetterAfter {
public Optional<Character> findIn(final String word) {
return Stream.of(word.split(""))
.filter(letter -> word.lastIndexOf(letter) > word.indexOf(letter))
.findFirst()
.map(letter -> letter.charAt(0));
}
}
static class FirstRepeatedLetterAfterWrapped implements FindLetter {
private final FirstRepeatedLetterAfter finder;
public FirstRepeatedLetterAfterWrapped(FirstRepeatedLetterAfter finder) {
this.finder = finder;
}
public Character findIn(final String word) {
return finder.findIn(word).orElse(null);
}
}
private static void commonFindFirstRepeatingTests(final FindLetter finder) {
assertAll(
() -> assertEquals('l', finder.findIn("hello")),
() -> assertEquals('h', finder.findIn("hellothere")),
() -> assertEquals('a', finder.findIn("magicalguru")),
() -> assertEquals('z', finder.findIn("abcdefghijklmnopqrstuvwxyzz")),
() -> assertNull(finder.findIn("once")),
() -> assertNull(finder.findIn(""))
);
}
@Test
void findFirstRepeatingBefore() {
commonFindFirstRepeatingTests(new FirstRepeatedLetterBefore());
}
@Test
void findFirstRepeatingBetter() {
commonFindFirstRepeatingTests(new FirstRepeatedLetterBetter());
}
@Test
void findFirstRepeatingAfter() {
commonFindFirstRepeatingTests(new FirstRepeatedLetterAfterWrapped(new FirstRepeatedLetterAfter()));
}
}
Popular Pragmatic Bookshelf topics
I thought that there might be interest in using the book with Rails 6.1 and Ruby 2.7.2. I’ll note what I needed to do differently here.
...
New
Hi @Margaret ,
On page VII the book tells us the example and snippets will be all using Elixir version 1.11
But on page 3 almost the en...
New
I ran this command after installing the sample application:
$ cards add do something --owner Brian
And got a file not found error:
Fil...
New
@noelrappin
Running the webpack dev server, I receive the following warning:
ERROR in tsconfig.json
TS18003: No inputs were found in c...
New
I think I might have found a problem involving SwitchCompat, thumbTint, and trackTint.
As entered, the SwitchCompat changes color to hol...
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
The test is as follows:
Scenario: Intersecting a scaled sphere with a ray
Given r ← ray(point(0, 0, -5), vector(0, 0, 1))
And s ← sphere...
New
When trying to run tox in parallel as explained on page 151, I got the following error:
tox: error: argument -p/–parallel: expected one...
New
When running tox for the first time, I got the following error:
ERROR: InterpreterNotFound: python3.10
I realised that I was running ...
New
@mfazio23
Android Studio will not accept anything I do when trying to use the Transformations class, as described on pp. 140-141. Googl...
New
Other popular topics
I know that -t flag is used along with -i flag for getting an interactive shell. But I cannot digest what the man page for docker run com...
New
From finance to artificial intelligence, genetic algorithms are a powerful tool with a wide array of applications. But you don't need an ...
New
Do the test and post your score :nerd_face:
:keyboard:
If possible, please add info such as the keyboard you’re using, the layout (Qw...
New
Continuing the discussion from Thinking about learning Crystal, let’s discuss - I was wondering which languages don’t GC - maybe we can c...
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
Was just curious to see if any were around, found this one:
I got 51/100:
Not sure if it was meant to buy I am sure at times the b...
New
Author Spotlight
Mike Riley
@mriley
This month, we turn the spotlight on Mike Riley, author of Portable Python Projects. Mike’s book ...
New
Programming Ruby is the most complete book on Ruby, covering both the language itself and the standard library as well as commonly used t...
New
zig/http.zig at 7cf2cbb33ef34c1d211135f56d30fe23b6cacd42 · ziglang/zig.
General-purpose programming language and toolchain for maintaini...
New
Categories:
Sub Categories:
Popular Portals
- /elixir
- /rust
- /wasm
- /ruby
- /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
- /zig
- /centos
- /deepseek
- /php
- /scala
- /react-native
- /lisp
- /textmate
- /sublime-text
- /nixos
- /debian
- /agda
- /django
- /deno
- /kubuntu
- /arch-linux
- /nodejs
- /revery
- /ubuntu
- /manjaro
- /spring
- /lua
- /diversity
- /julia
- /markdown
- /v








