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
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
Python Testing With Pytest - Chapter 2, warnings for “unregistered custom marks”
While running the smoke tests in Chapter 2, I get these...
New
Hello Brian,
I have some problems with running the code in your book. I like the style of the book very much and I have learnt a lot as...
New
Running mix deps.get in the sensor_hub directory fails with the following error:
** (Mix) No SSH public keys found in ~/.ssh. An ssh aut...
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
I found an issue in Chapter 7 regarding android:backgroundTint vs app:backgroundTint.
How to replicate:
load chapter-7 from zipfile i...
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
Hi, I need some help, I’m new to rust and was learning through your book. but I got stuck at the last stage of distribution. Whenever I t...
New
Hi, I’ve got a question about the implementation of PubSub when using a Phoenix.Socket.Transport behaviour rather than channels.
Before ...
New
@parrt
In the context of Chapter 4.3, the grammar Java.g4, meant to parse Java 6 compilation units, no longer passes ANTLR (currently 4....
New
Other popular topics
Write Elixir tests that you can be proud of. Dive into Elixir’s test philosophy and gain mastery over the terminology and concepts that u...
New
Design and develop sophisticated 2D games that are as much fun to make as they are to play. From particle effects and pathfinding to soci...
New
You might be thinking we should just ask who’s not using VSCode :joy: however there are some new additions in the space that might give V...
New
I’ve been hearing quite a lot of comments relating to the sound of a keyboard, with one of the most desirable of these called ‘thock’, he...
New
I ended up cancelling my Moonlander order as I think it’s just going to be a bit too bulky for me.
I think the Planck and the Preonic (o...
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
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
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
Get the comprehensive, insider information you need for Rails 8 with the new edition of this award-winning classic.
Sam Ruby @rubys
...
New
A concise guide to MySQL 9 database administration, covering fundamental concepts, techniques, and best practices.
Neil Smyth
MySQL...
New
Categories:
Sub Categories:
Popular Portals
- /elixir
- /rust
- /wasm
- /ruby
- /erlang
- /phoenix
- /keyboards
- /python
- /js
- /rails
- /security
- /go
- /swift
- /vim
- /clojure
- /java
- /emacs
- /haskell
- /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
- /sublime-text
- /textmate
- /nixos
- /debian
- /agda
- /django
- /deno
- /kubuntu
- /arch-linux
- /nodejs
- /revery
- /ubuntu
- /spring
- /manjaro
- /lua
- /diversity
- /julia
- /markdown
- /slackware









