0% found this document useful (0 votes)
1 views

Java Programming Exercises Volume Two Java Standard Library Christian Ullenboom instant download

Java Programming Exercises Volume Two focuses on enhancing coding skills with Java Standard Libraries through 149 tasks and solutions. It covers various programming paradigms and emphasizes clean code and thoughtful design. The book is designed for both beginners and professionals looking to deepen their understanding of Java programming.

Uploaded by

toscankrpic
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
1 views

Java Programming Exercises Volume Two Java Standard Library Christian Ullenboom instant download

Java Programming Exercises Volume Two focuses on enhancing coding skills with Java Standard Libraries through 149 tasks and solutions. It covers various programming paradigms and emphasizes clean code and thoughtful design. The book is designed for both beginners and professionals looking to deepen their understanding of Java programming.

Uploaded by

toscankrpic
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 90

Java Programming Exercises Volume Two Java

Standard Library Christian Ullenboom download

https://ebookbell.com/product/java-programming-exercises-volume-
two-java-standard-library-christian-ullenboom-58439762

Explore and download more ebooks at ebookbell.com


Here are some recommended products that we believe you will be
interested in. You can click the link to download.

Java Programming Exercises Volume Two Java Standard Library

https://ebookbell.com/product/java-programming-exercises-volume-two-
java-standard-library-58637134

Java Programming Exercises Volume One Language Fundamentals And Core


Concepts 1st Edition Christian Ullenboom

https://ebookbell.com/product/java-programming-exercises-volume-one-
language-fundamentals-and-core-concepts-1st-edition-christian-
ullenboom-58435736

Java Programming Exercises Volume One Language Fundamentals And Core


Concepts Christian Ullenboom

https://ebookbell.com/product/java-programming-exercises-volume-one-
language-fundamentals-and-core-concepts-christian-ullenboom-58439770

Java Programming Exercises Volume One Language Fundamentals And Core


Concepts Ullenboom

https://ebookbell.com/product/java-programming-exercises-volume-one-
language-fundamentals-and-core-concepts-ullenboom-58637136
Java From Zero Learn Java Programming Fast For Beginners To
Professionals The Complete Guide With Code Examples And Exercises To
Become A Professional Scott Brandt

https://ebookbell.com/product/java-from-zero-learn-java-programming-
fast-for-beginners-to-professionals-the-complete-guide-with-code-
examples-and-exercises-to-become-a-professional-scott-brandt-55838508

Java Programming Mindtap Course List 10th Edition 10th Joyce Farrell

https://ebookbell.com/product/java-programming-mindtap-course-
list-10th-edition-10th-joyce-farrell-50708988

Java Programming For Android Developers For Dummies 2nd Edition Barry
Burd

https://ebookbell.com/product/java-programming-for-android-developers-
for-dummies-2nd-edition-barry-burd-50864416

Java Programming Pandey Hari Mohan

https://ebookbell.com/product/java-programming-pandey-hari-
mohan-21999882

Java Programming 1e Rajkumar K

https://ebookbell.com/product/java-programming-1e-rajkumar-k-22019996
Java Programming Exercises
Take the next step in raising your coding skills and dive into the intricacies of Java Standard Libraries.
You will continue to raise your coding skills, and test your Java knowledge on tricky programming tasks,
with the help of the pirate Captain CiaoCiao. This is the second of two volumes which provide you with
everything you need to excel in your Java journey, including tricks that you should know in detail as a
professional, as well as intensive training for clean code and thoughtful design that carries even complex
software.

Features:

• 149 tasks with commented solutions on different levels


• For all paradigms: object‑oriented, imperative, and functional
• Clean code, reading foreign code, and object‑oriented modeling

With numerous best practices and extensively commented solutions to the tasks, these books provide the
perfect workout for professional software development with Java.
Java Programming Exercises
Volume Two: Java Standard Library

Christian Ullenboom
Designed cover image: Mai Loan Nguyen Duy, Rheinwerk Verlag GmbH

First edition published 2025


by CRC Press
2385 NW Executive Center Drive, Suite 320, Boca Raton FL 33431

and by CRC Press


4 Park Square, Milton Park, Abingdon, Oxon, OX14 4RN

CRC Press is an imprint of Taylor & Francis Group, LLC

©2023 Christian Ullenboom. First published in the German language under the title “Captain CiaoCiao erobert Java”
(ISBN 978‑3‑8362‑8427‑1) by Rheinwerk Verlag GmbH, Bonn, Germany.

Reasonable efforts have been made to publish reliable data and information, but the author and publisher cannot
assume responsibility for the validity of all materials or the consequences of their use. The authors and publishers
have attempted to trace the copyright holders of all material reproduced in this publication and apologize to
copyright holders if permission to publish in this form has not been obtained. If any copyright material has not been
acknowledged please write and let us know so we may rectify in any future reprint.

Except as permitted under U.S. Copyright Law, no part of this book may be reprinted, reproduced, transmitted, or
utilized in any form by any electronic, mechanical, or other means, now known or hereafter invented, including
photocopying, microfilming, and recording, or in any information storage or retrieval system, without written
permission from the publishers.

For permission to photocopy or use material electronically from this work, access www.copyright.com or contact the
Copyright Clearance Center, Inc. (CCC), 222 Rosewood Drive, Danvers, MA 01923, 978‑750‑8400. For works that are
not available on CCC please contact mpkbookspermissions@tandf.co.uk

Trademark notice: Product or corporate names may be trademarks or registered trademarks and are used only for
identification and explanation without intent to infringe.

ISBN: 978‑1‑032‑80117‑9 (hbk)


ISBN: 978‑1‑032‑79801‑1 (pbk)
ISBN: 978‑1‑003‑49555‑0 (ebk)

DOI: 10.1201/9781003495550

Typeset in Times
by codeMantra

Access the Support Material: https://routledge.com/9781032798011


Contents

About the Author xiii

Introduction 1
Previous Knowledge and Target Audience 1
Working with the Book 2
The Suggested Solutions 2
Use of the Book 3
Required Software 3
Used Java Version in the Book 4
JVM 4
Development Environment 4
Conventions 4
Helping Captain CiaoCiao and Bonny Brain 5

1 Advanced String Processing 6


Format Strings 6
Build ASCII Table ⭑ 6
Aligned Outputs ⭑ 8
Regular Expressions and Pattern Recognition 8
Quiz: Define Regex ⭑ 8
Determine Popularity in Social Media ⭑ 8
Detect Scanned Values ⭑ 9
Quiet Please! Defuse Shouting Texts ⭑ 10
Converting Time from AM/PM Format to 24‑Hour Format ⭑⭑ 11
Decompose Strings into Tokens 12
Split Address Lines with the StringTokenizer ⭑ 12
Split Sentences into Words and Reverse Them ⭑ 13
Check Relations between Numbers ⭑ 13
Convert A1 Notation to Columns and Rows ⭑⭑ 13
Parse Simple CSV Files with Coordinates ⭑ 14
Compress Strings Lossless by Runlength Encoding ⭑⭑⭑ 14
Character Encodings and Unicode Collation Algorithm 15
Quiz: Encoding for Unicode Characters ⭑ 15
Quiz: Order of Strings with and without Collator ⭑ 16
Suggested Solutions 16
Build ASCII Table 16
Aligned Outputs 17
Quiz: Define Regex 18
Determine Popularity in Social Media 19
Detect Scanned Values 19
Quiet Please! Defuse Shouting Texts 20
Converting Time from AM/PM Format to 24‑Hour Format 20
Split Address Lines with the StringTokenizer 21

v
vi Contents

Split Sentences into Words and Reverse Them 22


Check Relations between Numbers 23
Convert A1 Notation to Columns and Rows 24
Parse Simple CSV Files with Coordinates 25
Compress Strings Lossless by Runlength Encoding 26
Quiz: Encoding for Unicode Characters 28
Quiz: Order of Strings with and without Collator 28

2 Mathematics 30
The Class Math 30
Quiz: Rule of Thumb ⭑ 30
Check If Tin Tin Cheated on Rounding ⭑ 31
Huge and Very Precise Numbers 32
Calculate Arithmetic Mean of a Large Integer ⭑ 32
Number by Number over the Phone ⭑ 33
Develop Class for Fractions and Truncate Fractions ⭑⭑ 34
Suggested Solutions 35
Quiz: Rule of Thumb 35
Check If Tin Tin Cheated on Rounding 36
Calculate Arithmetic Mean of a Large Integer 37
Number by Number over the Phone 38
Develop Class for Fractions and Truncate Fractions 38

3 Locale, Date, and Time 42


Languages and Countries 42
Apply Country‑/Language‑Specific Formatting for Random Number ⭑ 43
Date and Time Classes 44
Formatting Date Output in Different Languages ⭑ 44
On Which Day Does Sir Francis Beaufort Celebrate His Birthday? ⭑ 45
Find All Friday the 13th ⭑ 45
Get Average Duration of Karaoke Nights ⭑ 46
Parse Different Date Formats ⭑⭑⭑ 46
Suggested Solutions 47
Apply Country‑/Language‑Specific Formatting for Random Number 47
Formatting Date Output in Different Languages 47
On Which Day Does Sir Francis Beaufort Celebrate His Birthday? 48
Find All Friday the 13th 50
Get Average Duration of Karaoke Nights 51
Parse Different Date Formats 52

4 Concurrent Programming with Threads 54


Create Threads 55
Create Threads for Waving and Flag Waving ⭑ 56
No More Waving Flags: End Threads ⭑ 56
Parameterize Runnable ⭑⭑ 56
Execute and Idle 57
Delay Execution by Sleeping Threads ⭑⭑ 57
Watch File Changes by Threads ⭑ 58
Catch Exceptions ⭑ 58
Thread Pools and Results 59
Using Thread Pools ⭑⭑ 60
Get Last Modification of Web Pages ⭑⭑ 60
Contents vii

Protect Critical Sections 61


Writing Memories into a Poetry Album ⭑ 62
Thread Cooperation and Synchronization Helper 64
Attending the Banquet with the Captains—Semaphore ⭑⭑ 64
Swearing and Insulting—Condition ⭑⭑ 65
Take Pens Out of Paintbox—Condition ⭑⭑ 65
Play Rock, Paper, Scissors—CyclicBarrier ⭑⭑⭑ 66
Find the Fastest Runner—CountDownLatch ⭑⭑ 67
Suggested Solutions 68
Create Threads for Waving and Flag Waving 68
No More Waving Flags: End Threads 69
Parameterize Runnable 70
Delay Execution by Sleeping Threads 70
Watch File Changes by Threads 72
Catch Exceptions 73
Using Thread Pools 74
Get Last Modification of Web Pages 75
Writing Memories into a Poetry Album 77
Attending the Banquet with the Captains—Semaphore 78
Swearing and Insulting—Condition 79
Take Pens Out of Paintbox—Condition 80
Play Rock, Paper, Scissors—CyclicBarrier 82
Find the Fastest Runner—CountDownLatch 83

5 Data Structures and Algorithms 85


The Types of the Collection API 86
Quiz: Search for StringBuilder ⭑ 87
Lists 88
Singing and Cooking: Traverse Lists and Check Properties ⭑ 88
Filter Comments from Lists ⭑ 89
Shorten Lists Because There Is No Downturn ⭑ 89
Eating with Friends: Compare Elements, Find Commonalities ⭑ 90
Check Lists for the Same Order of Elements ⭑ 90
And Now the Weather: Find Repeated Elements ⭑ 91
Generate Receipt Output ⭑ 92
Quiz: Arrays Decorated ⭑ 92
Quiz: Searched and Not Found ⭑ 92
Everything Tastes Better with Cheese: Insert Elements into Lists ⭑ 93
Quiz: With Nothing but Trouble ⭑ 93
Search Elements with the Iterator and Find Covid Cough ⭑⭑ 94
Move Elements, Play Musical Chairs ⭑ 95
Programming a Question Game with Planets ⭑⭑ 95
Sets 97
Form Subsets, Find Common Elements ⭑ 97
Quiz: Great Swords ⭑ 98
Get All Words Contained in a Word ⭑⭑ 99
Exclude Duplicate Elements with a UniqueIterator ⭑⭑ 99
Map Keys to Values 100
Convert Two‑Dimensional Arrays to Map ⭑ 100
Convert Text to Morse Code and Vice Versa ⭑ 101
Remember Word Frequency with Associative Memory ⭑⭑ 101
Read In and Read Out Colors ⭑⭑ 102
viii Contents

Read in Names and Manage Lengths ⭑ 103


Find Missing Characters ⭑⭑ 103
Calculate Number of Paths to the Three‑Headed Monkey ⭑⭑ 103
Manage Holidays in a Sorted Associative Store ⭑ 104
Quiz: Keys in a HashMap ⭑⭑ 105
Determine Commonality: Party Set and Souvenir ⭑ 106
Properties 106
Develop Convenient Properties Decorator ⭑⭑ 106
Stack and Queues 108
Program RPN Pocket Calculator ⭑ 108
BitSet 109
Forget No Ship ⭑ 109
Find Duplicate Entries and Solve the Animal Chaos ⭑ 110
Thread‑Safe Data Structures 110
Loading Ship ⭑⭑ 111
Handle Important Messages First ⭑⭑ 112
If Used Up, Create a New One ⭑⭑⭑ 113
Suggested Solutions 114
Quiz: Search for StringBuilder 114
Singing and Cooking: Traverse Lists and Check Properties 114
Filter Comments from Lists 116
Shorten Lists Because There Is No Downturn 117
Eating with Friends: Compare Elements, Find Commonalities 118
Check Lists for the Same Order of Elements 118
And Now the Weather: Find Repeated Elements 120
Generate Receipt Output 121
Quiz: Arrays Decorated 123
Quiz: Searched and Not Found 124
Everything Tastes Better with Cheese: Insert Elements into Lists 124
Quiz: With Nothing but Trouble 125
Search Elements with the Iterator and Find Covid Cough 126
Move Elements, Play Musical Chairs 128
Programming a Question Game with Planets 129
Form Subsets, Find Common Elements 130
Quiz: Great Swords 131
Get All Words Contained in a Word 132
Exclude Duplicate Elements with a UniqueIterator 133
Convert Two-Dimensional Arrays to Map 134
Convert Text to Morse Code and Vice Versa 136
Remember Word Frequency with Associative Memory 138
Read In and Read Out Colors 140
Read in Names and Manage Lengths 141
Find Missing Characters 143
Calculate the Number of Paths to the Three-Headed Monkey 145
Manage Holidays in a Sorted Associative Store 146
Quiz: Keys in a HashMap 147
Determine Commonality: Party Set and Souvenir 148
Develop Convenient Properties Decorator 148
Program RPN Pocket Calculator 150
Forget No Ship 151
Find Duplicate Entries and Solve the Animal Chaos 152
Loading Ship 153
Contents ix

Handle Important Messages First 154


If Used Up, Create a New One 155
Notes 156

6 Java Stream-API 157


Regular Streams with Their Terminal and Intermediate Operations 157
Hero Epic: Meet Stream API ⭑ 157
Quiz: Double Output ⭑ 158
Get the Beloved Captain from a List ⭑ 158
Frame Pictures ⭑ 159
Look and Say ⭑⭑ 160
Remove Duplicate Islands of Rare Earth Metals ⭑⭑⭑ 161
Where Are the Sails? ⭑⭑ 162
Buy the Most Popular Car ⭑⭑⭑ 163
Primitive Streams 163
Detect NaN in an Array ⭑ 163
Generate Decades ⭑ 164
Generate Array with Constant Content via Stream ⭑ 164
Draw Pyramids ⭑ 165
Teddies Labeled with Letters ⭑ 165
Get the Letter Frequency of a String ⭑ 166
From 1 to 0, from 10 to 9 ⭑⭑ 166
The Annual Octopus Contest ⭑⭑ 166
Merge Three int Arrays ⭑ 167
Determine Winning Combinations ⭑⭑ 167
Statistics 168
The Fastest and Slowest Paddlers ⭑ 168
Calculate Median ⭑⭑ 169
Calculate Temperature Statistics and Draw Charts ⭑⭑⭑ 169
Suggested Solutions 170
Hero Epic: Meet Stream API 170
Quiz: Double Output 176
Get the Beloved Captain from a List 176
Frame Pictures 177
Look and Say 178
Remove Duplicate Islands of Rare Earth Metals 179
Where Are the Sails? 181
Buy the Most Popular Car 182
Detect NaN in an Array 183
Generate Decades 183
Generate Array with Constant Content via Stream 184
Teddies Labeled with Letters 184
Draw Pyramids 185
Get the Letter Frequency of a String 185
From 1 to 0, from 10 to 9 186
The Annual Octopus Contest 187
Merge Three int Arrays 188
Determine Winning Combinations 189
The Fastest and Slowest Paddlers 189
Calculate Median 190
Calculate Temperature Statistics and Draw Charts 191
Note 195
x Contents

7 Files, Directories, and File Access 196


Path and Files 196
Display Saying of the Day ⭑ 197
Merge Hiding Places ⭑ 197
Create Copies of a File ⭑⭑ 197
Generate a Directory Listing ⭑ 198
Search for Large GIF Files ⭑ 198
Descend Directories Recursively and Find Empty Text Files ⭑ 198
Develop Your Own Utility Library for File Filters ⭑⭑⭑ 199
Random Access to File Contents 199
Output Last Line of a Text File ⭑⭑ 200
Suggested Solutions 200
Display Saying of the Day 200
Merge Hiding Places 201
Create Copies of a File 201
Generate a Directory Listing 202
Search for Large GIF Files 203
Descend Directories Recursively and Find Empty Text Files 204
Develop Your Own Utility Library for File Filters 205
Output Last Line of a Text File 208

8 Input/Output Streams 210


Direct Data Streams 211
Get the Number of Different Places (Read Files) ⭑ 211
Convert Python Program to Java (Write File) ⭑ 211
Generate Target Code (Write File) ⭑ 212
Convert File Contents to Lowercase (Read and Write File) ⭑ 213
Convert PPM Graphics to ASCII Grayscale ⭑⭑⭑ 213
Split Files (Read and Write Files) ⭑⭑ 215
Nesting Streams 215
Quiz: DataInputStream and DataOutputStream ⭑ 215
Compress Number Sequences with the GZIPOutputStream ⭑ 216
Serialization 216
(De)serialize Data for Chat and Convert It to Text ⭑⭑ 216
Quiz: Requirement for Serialization ⭑ 217
Save Last Inputs ⭑⭑ 217
Suggested Solutions 218
Get the Number of Different Places (Read Files) 218
Convert Python Program to Java (Write File) 219
Generate Target Code (Write File) 220
Convert File Contents to Lowercase (Read and Write File) 221
Convert PPM Graphics to ASCII Gray Scale 222
Split Files (Read and Write Files) 224
Quiz: DataInputStream and DataOutputStream 225
Compress Number Sequences with the GZIPOutputStream 228
(De)serialize Data for Chat and Convert Them to Text 229
Quiz: Requirement for Serialization 230
Save Last Inputs 231
Note 233
Contents xi

9 Network Programming 234


URL and URLConnection 234
Download Remote Images via URL ⭑ 235
Read Remote Text File from URL ⭑ 235
HTTP Client 236
Top News from Hacker News ⭑⭑ 236
Socket and ServerSocket 237
Implement a Swear Server and a Client ⭑⭑ 237
Implement a Port Scanner ⭑⭑ 237
Suggested Solutions 238
Download Remote Images via URL 238
Read Remote Text File from URL 239
Top News from Hacker News 240
Implement a Swear Server and a Client 241
Implement a Port Scanner 243

10 Process XML, JSON, and Other Data Formats 246


XML Processing with Java 247
Write XML File with Recipe ⭑ 247
Check If All Images Have an alt Attribute ⭑ 248
Writing Java Objects with JAXB ⭑ 248
Read in Jokes and Laugh Heartily ⭑⭑ 249
JSON 251
Hacker News JSON Exploit ⭑ 251
Read and Write Editor Configurations as JSON ⭑⭑ 252
HTML 253
Load Wikipedia Images with jsoup ⭑⭑ 253
Office Documents 253
Generate Word Files with Screenshots ⭑⭑ 253
Archives 254
Play Insect Sounds from ZIP Archive ⭑⭑ 254
Suggested Solutions 255
Write XML File with Recipe 255
Check If All Images Have an alt Attribute 258
Writing Java Objects with JAXB 259
Read in Jokes and Laugh Heartily 260
Hacker News JSON Exploit 261
Read and Write Editor Configurations as JSON 262
Load Wikipedia Images with jsoup 263
Generate Word Files with Screenshots 264
Play Insect Sounds from ZIP Archive 265
Note 266

11 Database Access with JDBC 267


Database Management Systems 267
Prepare H2 Database ⭑ 268
Database Queries 268
Query All Registered JDBC Drivers ⭑ 268
Build Database and Execute SQL Script ⭑ 269
Insert Data into the Database ⭑ 270
Insert Data into the Database in Batch Mode ⭑ 271
xii Contents

Insert Data with Prepared Statements ⭑ 271


Request Data ⭑ 272
Interactive Scrolling through the ResultSet ⭑ 272
Pirate Repository ⭑⭑ 272
Query Column Metadata ⭑ 273
Suggested Solutions 274
Query All Registered JDBC Drivers 274
Build Database and Execute SQL Script 274
Insert Data into the Database 275
Insert Data into the Database in Batch Mode 276
Insert Data with Prepared Statements 277
Request Data 277
Interactive Scrolling through the ResultSet 278
Pirate Repository 279
Query Column Metadata 282

12 Operating System Access 284


Console 284
Colored Console Outputs ⭑ 285
Properties 286
Windows, Unix, or macOS? ⭑ 286
Unify Command‑Line Properties and Properties from Files ⭑ 286
Execute External Processes 287
Read the Battery Status via Windows Management Instrumentation ⭑⭑ 287
Suggested Solutions 288
Colored Console Outputs 288
Windows, Unix, or macOS? 288
Unify Command‑Line Properties and Properties from Files 289
Read the Battery Status via Windows Management Instrumentation 290

13 Reflection, Annotations, and JavaBeans 294


Reflection API 294
Create UML Class Diagram with Inheritance Relationships ⭑ 295
Create UML Class Diagram with Properties ⭑ 296
Generate CSV Files from List Entries ⭑⭑ 297
Annotations 297
Create CSV Documents from Annotated Instance Variables ⭑⭑ 297
Suggested Solutions 298
Create UML Class Diagram with Inheritance Relationships 298
Create UML Class Diagram with Properties 299
Generate CSV Files from List Entries 301
Create CSV Documents from Annotated Instance Variables 301

Epilogue 307
Code Golf Stack Exchange 307
Project Euler 307
Daily Programmer 307
Rosetta Code 308
About the Author

Christian Ullenboom s tarted his programming journey at the tender age of ten, typing his first lines of
code into a C64. After mastering assembler programming and early BASIC extensions, he found his call‑
ing on the island of Java, following his studies in computer science and psychology. Despite indulging in
Python, JavaScript, TypeScript, and Kotlin vacations, he remains a savant of all things Java.
For over 20 years, Ullenboom has been a passionate software architect, Java trainer (check out http://
www.tutego.com), and IT specialist instructor. His expertise has resulted in a number of online video
courses and reference books:

• Java: The Comprehensive Guide (ISBN‑13: 978‑1493222957)


• Java ist auch eine Insel: Java programmieren lernen mit dem umfassenden Standardwerk für
Java‑Entwickler (ISBN‑13: 978‑3836287456)
• Java SE 9 Standard‑Bibliothek: Das Handbuch für Java‑Entwickler (ISBN‑13: 978‑3836258746)
• Captain CiaoCiao erobert Java: Das Trainingsbuch für besseres Java (ISBN‑13:
978‑3836284271)
• Spring Boot 3 und Spring Framework 6: Professionelle Enterprise‑Anwendungen mit Java
( ISBN‑13: 978‑3836290494)

Christian Ullenboom has been spreading Java love through his books for years, earning him the coveted
title of Java Champion from Sun (now Oracle) way back in 2005. Only a select few—about 300 world‑
wide—have achieved this status, making him a true Java superstar.
As an instructor, Ullenboom understands that learning by doing is the most effective way to master a
skill. So, he has compiled a comprehensive catalog of exercises that accompany his training courses. This
book features a selection of those exercises, complete with documented solutions.
His roots are in Sonsbeck, a small town in the Lower Rhine region of Germany.

xiii
Introduction

Many beginners in programming often ask themselves, “How can I strengthen my skills as a developer?
How can I become a better programmer?” The answer is simple: study, attend webinars, learn, repeat,
practice, and discuss your work with others. Many aspects of programming are similar to learning new
skills. Just as a book can’t teach you how to play a musical instrument, watching the Fast and the Furious
movie series won’t teach you how to drive. The brain develops patterns and structures through repeated
practice. Learning a programming language and a natural language have many similarities. Consistent
use of the language, and the desire and need to express and communicate in it (just as you need to do so
to order a burger or a beer), leads to gradual improvement in skills.
Books and webinars on learning a programming language are available, but reading, learning, prac‑
ticing, and repeating are just one aspect of becoming a successful software developer. To create effective
software solutions, you need to creatively combine your knowledge, just as a musician regularly practices
finger exercises and maintains their repertoire. The more effective your exercises are, the faster you will
become a master. This book aims to help you progress and gain more hands‑on experience.
Java 21 declares more than 2300 classes, about 1400 interfaces, around 140 enumerations, approxi‑
mately 500 exceptions, and a few annotation types and records are added to this. However, in practical
terms, only a small subset of these types proves to be relevant. This book selects the most important types
and methods for tasks, making them motivating, and following Java conventions. Alternative solutions
and approaches are also presented repeatedly. The goal is to make non‑functional requirements clear
because the quality of programs is not just about “doing what it should.” Issues such as correct indentation,
following naming conventions, proper use of modifiers, best practices, and design patterns are essential.
The proposed solutions aim to demonstrate these principles, with the keyword being Clean Code.

PREVIOUS KNOWLEDGE AND TARGET AUDIENCE


The book is aimed at Java developers who are either new to Java or are already advanced and wish to learn
more about the Java SE standard libraries. The intended audience includes:

• Computer science students


• IT specialists
• Java programmers
• Software developers
• Job applicants

The book is centered around tasks and fully documented solutions, with detailed explanations of Java
peculiarities, good object‑oriented programming practices, best practices, and design patterns. The exer‑
cises are best solved with a textbook, as this exercise book is not a traditional textbook. A useful approach
is to work through a topic with a preferred textbook before attempting the exercises that correspond to it.

DOI: 10.1201/9781003495550-1 1
2 Java Programming Exercises

The first set of tasks are designed for programming beginners who are new to Java. As you gain more
experience with Java, the tasks become more challenging. Therefore, there are tasks for both beginners
and advanced developers.
The Java Standard Edition is augmented by numerous frameworks and libraries. However, this
exercise book does not cover specific libraries or Java Enterprise frameworks like Jakarta EE or Spring
(Boot). There are separate exercise books available for these environments. Additionally, the book does
not require the use of tools like profiling tools, as these are beyond the scope of the book.

WORKING WITH THE BOOK


The task book is organized into different sections. The first section covers the Java language, followed
by selected areas of the Java standard library, such as data structures or file processing. Each area is
accompanied by programming tasks and “quiz” questions that contain surprises. Each section starts with
a small motivation and characterization of the topic, followed by the exercises. Additional tips and hints
are provided for particularly challenging assignments, while other exercises offer optional extensions for
further exploration.
The majority of exercises are independent of each other, making it easy for readers to dive in any‑
where. However, in the chapter on imperative programming, some tasks build on each other to develop a
larger program, and the same goes for the chapter on object‑oriented programming. The problem defini‑
tions make this clear, and more complex programs help to provide context for understanding different
language characteristics. Furthermore, a more complex program can motivate readers to continue.
The exercises are rated with one, two, or three stars to indicate their complexity, although this rating
is subjective to the author.

1 star ★: Simple exercises, suitable for beginners. They should be easy to solve without much
effort. Often only transfer of knowledge is required, for example, by writing down things that
are in a textbook differently.
2 stars ★★: The effort is higher here. Different techniques have to be combined. Greater creativity
is required.
3 stars ★★★: Assignments with three stars are more complex, require recourse to more prior
knowledge, and sometimes require research. Frequently, the tasks can no longer be solved with
a single method, but require multiple classes that must work together.

THE SUGGESTED SOLUTIONS


The task book provides at least one suggested solution for each problem. The term “sample solution” is
not used to avoid implying that the given solution is the best one and that all other solutions are useless.
Readers are encouraged to compare their solutions with the proposed solution and can be satisfied if
their solution is more elegant. All proposed solutions are commented, making it possible to follow all
steps well.
The suggested solutions are compiled at the end of each chapter to reduce the temptation to look into
a solution directly after the task, which takes the fun out of solving the task. The suggested solutions can
also be found on the website https://github.com/ullenboom/captain‑ciaociao. Some solutions contain com‑
ments of the type //tag::solution[], which marks the parts of the solutions printed in the book.
 • Introduction 3

USE OF THE BOOK


To become a software developer, you must master the art of turning problems into code, and that’s where
practice and role models come in. While there are plenty of exercises available online, they’re often
disorganized, poorly documented, and outdated. That’s where this book shines, by offering a systematic
approach to tasks and well‑thought‑out solutions. Studying these solutions and reading code in general
helps the brain develop patterns and solutions that can be applied to future coding challenges. It’s like
reading the Bible; you need to read to understand and learn. Surprisingly, many software developers
write code without bothering to read others’ code, which can lead to confusion and misunderstand‑
ing. Reading good code elevates our writing skills by building patterns and solutions that our brains
unconsciously transfer to our own code. Our brains form neuronal structures independently based on
templates, and the quality of the input we receive matters greatly. Therefore, we should only feed our
brains with good code, as bad solutions make for bad models. The book covers important topics such as
exception handling or error handling, discussing the correct input values, identifying erroneous states,
and how to handle them. In software, things can and will go wrong, and we must be prepared to deal
with the less‑than‑perfect world.
It’s easy for developers to get stuck in their ways of writing code, which is why it’s important to
explore new approaches and “expand our vocabulary”, so to speak. For Java developers, libraries are their
vocabulary, but too many enterprise Java developers write massive, non‑object‑oriented code. The solu‑
tion is to continuously improve object‑oriented modeling, which is precisely what this book demonstrates.
It introduces new methods, creates new data types, and minimizes complexity. Additionally, functional
programming is becoming increasingly important in Java development, and all solutions in this book take
advantage of modern language features.
While some solutions may appear overly complex, the tasks and proposed solutions in this book can
help developers improve their ability to concentrate and follow through with steps. In practice, the ability
to concentrate and quickly comprehend code is crucial for developers. Often, developers must join a new
team and be able to understand and modify unfamiliar source code, and possibly fix bugs. Those who
wish to expand upon existing open‑source solutions can also benefit from honing their concentration skills
through these exercises.
In addition to its emphasis on the Java programming language, syntax, libraries, and object orien‑
tation, this book provides numerous side notes on topics such as algorithms, the historical evolution of
programming, comparisons to other programming languages, and data formats. These additional insights
and perspectives offer readers a more well‑rounded understanding of software development beyond just
the technical aspects.
If you’re looking for one more reason to add this book to your collection, it doubles as a fantastic
sleep aid!

REQUIRED SOFTWARE
While solving a task with just a pen and paper is possible in theory, modern software development
requires the proper use of tools. Knowing programming language syntax, object‑oriented modeling,
and libraries is just the tip of the iceberg. Understanding the JVM, using tools like Maven and Git for
version management, and becoming proficient in an IDE are all crucial aspects of professional software
development. Some developers can even perform magic in their IDE, generating code and fixing bugs
automatically.
4 Java Programming Exercises

USED JAVA VERSION IN THE BOOK


While Java 8 remains prevalent in enterprise settings, it’s crucial for learners to become acquainted with
the latest language features. Accordingly, whenever feasible, the suggested solutions in this book leverage
Java 17. Not only is this version equipped with Long‑term Support (LTS), but runtime environment pro‑
viders also offer extensive support, ensuring that the release retains its relevance for an extended period.

JVM
If we want to run Java programs, we need a JVM. In the early days, this was easy. The runtime environ‑
ment first came from Sun Microsystems, later from Oracle, which took over Sun. Today, it is much more
confusing. Although a runtime environment can still be obtained from Oracle, the licensing terms have
changed, at least for Java 8 up to Java 16. Testing and development are possible with the Oracle JDK,
but not in production. In this case, Oracle charges license fees. As a consequence, various institutions
compile their own runtime environments from the OpenJDK, the original sources. The best known are
Eclipse Adoptium (https://adoptium.net/), Amazon Corretto (https://aws.amazon.com/de/corretto), Red
Hat OpenJDK (https://developers.redhat.com/products/openjdk/overview) and others such as those from
Azul Systems or Bellsoft. There is no specific distribution that readers are required to follow.

Development Environment
Java source code is just plain text, so technically a simple text editor is all you need. However, relying
solely on Notepad or vi for productivity is like trying to win a race on a tricycle. Modern integrated
development environments support us with many tasks: color highlighting of keywords, automatic code
completion, intelligent error correction, insertion of code blocks, visualization of states in the debug‑
ger, and much more. It is therefore advisable to use a full development environment. Four popular IDEs
are: IntelliJ, Eclipse, Visual Studio Code, and (Apache) NetBeans. Just like with Java runtime environ‑
ments, the choice of IDE is left to the reader. Eclipse, NetBeans, and Visual Studio Code are all free
and open‑source, while IntelliJ Community Edition is also free, but the more advanced IntelliJ Ultimate
Edition will cost you some cash.
Halfway through the book, we delve into implementing project dependencies using Maven in a few
places.

CONVENTIONS
Code is written in fix width font, filenames are italicized. To distinguish methods from attributes,
methods always have a pair of parentheses, such as in “the variable max contains the maximum” or “it
returns max() the maximum”. Since methods can be overloaded, either the parameter list is named, as in
equals(Object), or an ellipsis abbreviates it, such as in “various println(…) methods”. If a group
of identifiers is addressed, * is written, like print*(...) prints something on the screen.
In the suggested solutions, there are usually only the relevant code snippets, so as not to blow up the
book volume. The name of the file is mentioned in the listing caption, like this:
VanillaJava.java

class VanillaJava { }
 • Introduction 5

Sometimes, we need to flex our terminal muscles and execute programs from the command line (also
known as console or shell). Since each command‑line program has its own prompt sequence, it is symbol‑
ized here in the book with a $. The user’s input is set in bold. Example:

$ java ‑version
java version "17.0.5" 2022‑10‑18 LTS
Java(TM) SE Runtime Environment (build 17.0.5+9‑LTS‑191)
Java HotSpot(TM) 64‑Bit Server VM (build 17.0.5+9‑LTS‑191, mixed mode,
sharing)

If the Windows command line is explicitly meant, the prompt character > is set:

> netstat ‑e
Interface Statistics

Received Sent

Bytes 218927776 9941980


Unicast packets 162620 64828
Non‑unicast packets 276 668
Discards 0 0
Errors 0 0
Unknown protocols 0

HELPING CAPTAIN CIAOCIAO AND BONNY BRAIN


Ahoy there! Once upon a time, Captain CiaoCiao and Bonny Brain lent ye a hand with a certain matter we
won’t speak of. And now, ye owe them a favor. But fear not, for it will be worth yer while to assist them on their
latest venture. Join the daring duo and their loyal crew as they sail the seven seas, striking deals with unsa‑
vory characters across the globe. Their secret hideout is on the island of Baloo, where the currency of choice
is Liretta. With a crew hailing from all corners of the world, all program outputs be in English, me hearties.
Advanced String
Processing 1
After dealing with basic data types around characters and strings in another chapter, we will now discuss
advanced string processing. The topics are formatted output, regular expressions, and string splitting.
Prerequisites

• Be able to format strings.


• Be able to match, search, and replace with regular expressions.
• Be able to split strings.
• Understand character encodings and UTF‑8.

Data types used in this chapter:

• java.util.Formatter
• java.lang.String
• java.util.regex.Pattern
• java.util.regex.Matcher
• java.util.Scanner

FORMAT STRINGS
There are different ways in Java to format strings, numbers, and temporal data as a string. In the package
java.text, you can find the classes MessageFormat, DateFormat, and DecimalFormat as well
as the class Formatter and in String the method String.format(…). The next tasks can be solved
using the formatting strings from Formatter in a rather easy way.

Build ASCII Table ⭑


Bonny Brain has installed a new app on her Aye Phone that shows her the ASCII alphabet:

$ ascii
Usage: ascii [‑adxohv] [‑t] [char‑alias...]
‑t = one‑line output ‑a = vertical format
‑d = Decimal table ‑o = octal table ‑x = hex table ‑b binary table
‑h = This help screen ‑v = version information
Prints all aliases of an ASCII character. Args may be chars, C \‑escapes,
English names, ^‑escapes, ASCII mnemonics, or numerics in decimal/octal/hex.

6 DOI: 10.1201/9781003495550-2
1 • Advanced String Processing 7

Dec Hex Dec Hex Dec Hex Dec Hex Dec Hex Dec Hex Dec Hex Dec Hex
0 00 NUL 16 10 DLE 32 20 48 30 0 64 40 @ 80 50 P 96 60 ' 112 70 p
1 01 SOH 17 11 DC1 33 21 ! 49 31 1 65 41 A 81 51 Q 97 61 a 113 71 q
2 02 STX 18 12 DC2 34 22 " 50 32 2 66 42 B 82 52 R 98 62 b 114 72 r
3 03 ETX 19 13 DC3 35 23 # 51 33 3 67 43 C 83 53 S 99 63 c 115 73 s
4 04 EOT 20 14 DC4 36 24 $ 52 34 4 68 44 D 84 54 T 100 64 d 116 74 t
5 05 ENQ 21 15 NAK 37 25 % 53 35 5 69 45 E 85 55 U 101 65 e 117 75 u
6 06 ACK 22 16 SYN 38 26 & 54 36 6 70 46 F 86 56 V 102 66 f 118 76 v
7 07 BEL 23 17 ETB 39 27 ' 55 37 7 71 47 G 87 57 W 103 67 g 119 77 w
8 08 BS 24 18 CAN 40 28 ( 56 38 8 72 48 H 88 58 X 104 68 h 120 78 x
9 09 HT 25 19 EM 41 29 ) 57 39 9 73 49 I 89 59 Y 105 69 i 121 79 y
10 0A LF 26 1A SUB 42 2A * 58 3A : 74 4A J 90 5A Z 106 6A j 122 7A z
11 0B VT 27 1B ESC 43 2B + 59 3B ; 75 4B K 91 5B [ 107 6B k 123 7B {
12 0C FF 28 1C FS 44 2C , 60 3C <   76 4C L 92 5C \ 108 6C l 124 7C |
13 0D CR 29 1D GS 45 2D ‑ 61 3D =   77 4D M 93 5D ] 109 6D m 125 7D }
14 0E SO 30 1E RS 46 2E . 62 3E >   78 4E N 94 5E ^ 110 6E n 126 7E ~
15 0F SI 31 1F US 47 2F / 63 3F ?     79 4F O 95 5F _ 111 6F o 127 7F DEL

However, their Aye Phone doesn’t have such a widescreen, and the first two blocks are not visible char‑
acters anyway.

Task:

• Write a program that prints all ASCII characters from position 32 to 127 in the same formatting
as the Unix program ascii does.
• At position 127, write DEL.
8 Java Programming Exercises

Aligned Outputs ⭑
Captain CiaoCiao needs a table of the following type for a listing:

Dory Dab paid


Bob Banjo paid
Cod Buri paid
Bugsy not paid

Task:

• Write a method printList(String[] names, boolean[] paid) that prints a collec‑


tion on the screen. The first string array contains all names, the second array contains informa‑
tion whether the person has paid or not.
• All names can be of different lengths, but the texts in the second column should be aligned.
• The longest string in the first column has a distance of four spaces to the second column.
• If passed arrays are null, a NullPointerException must be thrown.

REGULAR EXPRESSIONS AND


PATTERN RECOGNITION
Regular expressions are a curse and a blessing for many. Used incorrectly, they lead to programs that are
impossible to read later, used correctly, they shorten the program massively and contribute to clarity.
The next exercises will show that we can use regular expressions to test whether

1. A string completely matches a regular expression.


2. A partial string exists and if so, find out where, and then replace it.

Later, we will also use regular expressions to specify separators and decompose strings.

Quiz: Define Regex ⭑


What does the regex look like to match or find the following?

• A string of exactly 10 digits.


• A string of 5–10 digits and letters.
• A string ending in ., ! or ? like a sentence.
• A nonempty string that does not contain digits.
• An official title or a name title: Prof., Dr., Dr. med., Dr. h.c. in the string.

Determine Popularity in Social Media ⭑


Of course Captain CiaoCiao is active on social media; his identifier is #CaptainCiaoCiao or @
CaptainCiaoCiao.
Now Captain CiaoCiao wants to know how popular he is.
1 • Advanced String Processing 9

Task:

• Given an aggregated text with messages; how often does #CaptainCiaoCiao or @


CaptainCiaoCiao occur there?

Example:

• For the following input, the result is 2.


Make me a baby #CaptainCiaoCiao
Hey @CaptainCiaoCiao, where is the recruitment test?
What is a hacker's favorite pop group? The Black IP's.

Detect Scanned Values ⭑


Bonny Brain receives scanned lists of numbers that need to be processed electronically. In the first step,
it sends the scans through an OCR recognizer, and the result is ASCII text. The numbers from the OCR
recognition always look like this:
Representation of the numbers 0 to 9

000 11 22 333 4 4 5555 6 77777 888 9999


0 00 111 2 2 3 4 4 5 6 7 8 8 9 9
0 0 0 11 2 33 4444 555 6666 7 888 9999
00 0 11 2 3 4 5 6 6 7 8 8 9
000 11l1 2222 333 4 555 666 7 888 9
10 Java Programming Exercises

Task:

• Given is a line from the scan with numbers from the format shown. Convert the numbers to an
integer.
• There could be missing spaces after the last digit, and there could be several spaces between
the large characters.

Example:

• If the string (written in the text block syntax) is


String ocr = """
4 4 77777 11 11 4 4 22
4 4 7 111 111 4 4 2 2
4444 7 11 11 4444 2
4 7 11 11 4 2
4 7 11l1 11l1 4 2222""";
so the desired result should be 471142.

If you want to play around with the strings, you can find a way at https://patorjk.com/software/taag/#p=
display&f=Alphabet&t=0123456789.

Quiet Please! Defuse Shouting Texts ⭑


Captain CiaoCiao often gets letters, and the senders often SCREAM in capital letters—how nasty for his
eyes.

Task:

• Write a method String silentShoutingWords(String) that converts all capitalized


words over three letters in length to lowercase.
1 • Advanced String Processing 11

Example:

• silentShoutingWords("AY Captain! Smutje MUST GO!") → "AY Captain!


Smutje must GO!"

Converting Time from AM/PM Format


to 24‑Hour Format ⭑⭑
Bonny Brain frequently gets messages where the time is given in AM and PM.

We raid the harbor at 11:00 PM and meet on the amusement mile at 1:30 AM.

Bonny Brain doesn’t like that; she wants only the 24‑hour count of Military Time.

Task:

• Write a converter that converts strings with AM/PM (case‑insensitive, even with periods) to
Military Time. As a reminder, 12:00 AM is 00:00, and 12:00 PM is 12:00.

Examples:

• "Harbour: 11:00 PM, entertainment districts: 1:30 a.m.!" → Harbour:


2300, entertainment districts: 0130!"
• "Get out of bed: 12:00AM, bake a cake: 12 PM." → "Get out of bed:
0000, bake a cake: 1200"
12 Java Programming Exercises

DECOMPOSE STRINGS INTO TOKENS


Tokenizing is the opposite of constructing and formatting a string. A string is split into substrings, with
separators determining the separation points. Java provides various classes for tokenizing strings and
input. The separators can be symbols or strings described by regular expressions. The split(…) method
of the String class works with regular expressions just like the Scanner, and the StringTokenizer
class does not.

Split Address Lines with the StringTokenizer ⭑


The software of Captain CiaoCiao has to evaluate addresses consisting of three or four lines.
The meaning of the lines

LINE CONTENT OPTIONAL


1 name no
2 street no
3 city no
4 country yes

The lines are separated with a line break. There are four valid separator symbols or sequences:
LF is the abbreviation for “line feed” and CR for “carriage return”; in old teleprinters, CR moved the
carriage to the first column, and LF pushed the paper up.
Traditionally, DOS and Microsoft Windows use the combination \r\n, while Unix systems use \n.
Task:

• Break a newline‑separated string into four lines, and assign the lines to the variables name,
street, city, and country.
• If a fourth line with the country name is not given, let country be "Drusselstein".
• Reassemble the line as a CSV line separated by semicolons.

Examples:

• "Boots and Bootles\n21 Pickle Street\n424242 Douglas\nArendelle" →


Boots and Bootles;21 Pickle street;424242 Douglas;Arendelle
• "Doofenshmirtz Evil Inc.\nStrudelkuschel 4427\nDanville" →
Doofenshmirtz Evil Inc.;Strudelkuschel 4427;Gimmelshtump;
Drusselstein

TABLE 1.1 Line break


CHARACTER
(ABBREVIATION) DECIMAL HEXADECIMAL ESCAPE SEQUENCE
LF 10 0A \n
CR 13 0D \r
CR LF 13 10 0D 0A \r\n
LF CR 10 13 0A 0D \n\r
1 • Advanced String Processing 13

Split Sentences into Words and Reverse Them ⭑


Bonny Brain is waiting for a message, but something went wrong with the transmission—all the words
are reversed!

erehW did eht etarip esahcrup sih kooh? tA eht dnah‑dnoces pohs!

Task:

1. Break the string into words. Separators of words are spaces and punctuation marks.
2. Turn over all the words one by one.
3. Output the words one after the other, separated by a space. The punctuation marks and other
separators are not critical.

Example:

• "erehW did eht etarip esahcrup sih kooh? tA eht dnah‑dnoces pohs!"
→ "Where did the pirate purchase his hook At the hand second shop"

Check Relations between Numbers ⭑


Captain CiaoCiao practices archery, and he records the scores from 0 to 10 in a list. He also notes if he got
better, worse, or if the score stays the same. It may look like this:

1 < 2 > 1 < 10 = 10 > 2

Goldy Goldfish has the task of checking the relation signs <, > and =.
Task:

• Write a program that gets a string like the one in the example and returns true if all relation
signs are correct, and false otherwise.

Examples:

• 1 < 2 > 1 < 10 = 10 > 2 → true


• 1 < 1 → false
• 1 < → false
• 1 → true

Convert A1 Notation to Columns and Rows ⭑⭑


Captain CiaoCiao keeps records of his loot and uses spreadsheets. With his staff, he discusses the figures,
and to address the cells he uses the column and row index; for example, he says 4–16 to refer to the 4th
column and the 16th row. Now he has heard of a whole new way to name cells, A1 notation, which uses a
new kind of software called ECKSEL. This involves coding the column with letters from A to Z, accord‑
ing to the following scheme:

A, B, …, Z, AA, …, AZ, BA, …, ZZ, AAA, AAB, …

The lines are still described with numbers. Thus, A2 stands for cell 1–2.
14 Java Programming Exercises

Since Captain CiaoCiao has its difficulties with A1 notation, the specification is to be converted back
to numeric columns and rows.
Task:

• Write a method parseA1Notation(String) that gets a string in A1 notation and returns


an array with two elements, in which at position 0 is the column and at position 1 is the row.

Examples:

• parseA1Notation("A1") → [1, 1]
• parseA1Notation("Z2") → [26, 2]
• parseA1Notation("AA34") → [27, 34]
• parseA1Notation("BZ") → [0, 0]
• parseA1Notation("34") → [0, 0]
• parseA1Notation(" ") → [0, 0]
• parseA1Notation("") → [0, 0]

Parse Simple CSV Files with Coordinates ⭑


Bonny Brain notes the locations with loot in a CSV file coordinates.csv, where the coordinates are
­floating‑point numbers separated by commas.
For example, the file looks like this:
com/tutego/exercise/string/coordinates.csv

20.091612,‑155.676695
23.087301,‑73.643472
21.305452,‑71.690421

Task:

• Create a CSV file manually. It should contain several lines with coordinates; a comma sepa‑
rates the coordinates.
• A Java program should read the CSV file and output an HTML file with SVG for the polygon
course on the screen.
• Use the class Scanner to parse the file. Make sure to initialize the Scanner with
useLocale(Locale.ENGLISH) if your locale is not English by default.

Example: For the upper block, we want to create

<svg height="210" width="500">


<polygon points="20.091612,‑155.676695 23.087301,‑73.643472 21.305452,‑
71.690421 " style="fill:lime;stroke:purple;stroke‑width:1" />
</svg>

Compress Strings Lossless by Runlength Encoding ⭑⭑⭑


To reduce the volume of data, files are often compressed. There are different compression algorithms;
some are lossy like vowel removal, others work without loss like ZIP. Lossy compression is found in
images, JPEG is a good example. Depending on the degree of compression, the image quality degrades.
In JPEG, very high compression results in an image with strong artifacts.
1 • Advanced String Processing 15

A simple lossless compression is run‑length encoding. The idea is to combine a sequence of ­identical
symbols so that only the number and the symbol are written. The graphic format GIF, for example, uses
this form of compression. Therefore, images with many monochrome lines are also smaller than, for
example, images in which each pixel has a different color.
The next task is about run‑length encoding. Suppose a string consists of a sequence of . (dot) and ‑
(minus sign), such as:

‑‑....‑‑‑‑‑‑‑‑..‑

To shorten the length of strings, we can first write the symbol followed by the number of symbols. The
string with 17 characters could be shortened to the following string with 9 characters:

‑2.4‑8.2‑

Task:

1. Create a new class SimpleStringCompressor.


2. Write a static method String compress(String) that encodes sequences of . and ‑
according to the described algorithm: First comes the character, then the number.
3. Write a decoder String decompress(String) that unpacks the compressed string. Let
decompress(compress(input)) be equal to input.

Extensions:

• The program shall be able to handle all nondigits.


• Refine the program so that the number is omitted if the character occurs only exactly once.

CHARACTER ENCODINGS AND


UNICODE COLLATION ALGORITHM
Over the network and in the file system, everything is stored as a byte. One byte can have 256 different
values, but this is not enough for all the characters in the world. Therefore, there are character encodings,
which can encode all characters in the world in a certain way. The character encodings differ thereby.
Sometimes characters are mapped to a fixed number of bytes, sometimes characters are mapped to a dif‑
ferent number of bytes, or perhaps some characters are just not recognized at all. Java supports all kinds
of character encodings, but the most important character encoding today is the UTF‑8 encoding.

Quiz: Encoding for Unicode Characters ⭑


What characterizes an UTF‑8 encoding?
16 Java Programming Exercises

Quiz: Order of Strings with and without Collator ⭑


After comparing with the Comparator, are the outputs positive, negative, or 0?

Comparator<String> comparator = Comparator.naturalOrder();


System.out.println( comparator.compare( "a", "ä" ) );
System.out.println( comparator.compare( "ä", "z" ) );
System.out.println( comparator.compare( "n", "ñ" ) );
System.out.println( comparator.compare( "ñ", "o" ) );

Comparator<Object> collatorDE = Collator.getInstance( Locale.GERMAN );


System.out.println( collatorDE.compare( "a", "ä" ) );
System.out.println( collatorDE.compare( "ä", "z" ) );
System.out.println( collatorDE.compare( "n", "ñ" ) );
System.out.println( collatorDE.compare( "ñ", "o" ) );

SUGGESTED SOLUTIONS

Build ASCII Table


com/tutego/exercise/string/PrintAsciiTable.java

System.out.println( "Dec Hex ".repeat( 6 ) );

for ( int row = 0; row < 16; row++ ) {


for ( int asciiCode = 32 + row; asciiCode <= 127; asciiCode += 16 ) {
System.out.printf(
"%1$3d %1$X %2$s ", asciiCode,
asciiCode == 127 ? "DEL" : Character.toString( asciiCode ) );
}
System.out.println();
}

First, the program writes the table header, in which the string “Dec Hex” for the six columns is set six
times in a row with spacing.
The generated table has 16 rows, which generates a loop. In principle, we could also dynamically
calculate the number of rows from the start and end values and the number of columns (six in our case).
However, we know that if we start at position 32, and end at 127, with 6 columns we need 16 rows.
The inner loop writes all columns for a given row. At the top left is the first element, the space char‑
acter. To the right, the character increases not by one, but by 16, which is, therefore, the loop counter.
In the next line, we don’t start at 32 but at 33, the pattern here is the following: the start value of the
inner loop is 32 + row, so 32 plus the row number. Altogether, the loop ends when the ASCII code has
reached 127.
Within the inner loop’s body, the character is required to be displayed as a string. Essentially, each
character is outputted as a string. The conditional operator verifies whether the character at positions 127
is the DEL character; all other characters are converted to a string of length 1 through the Character
method. The format string consists of three components: the first two parts access the first format argu‑
ment and begin by displaying the character’s position as a decimal number, followed by its number in
hexadecimal format. The integer is left‑padded with white space, while the hexadecimal number doesn’t
1 • Advanced String Processing 17

require any width information, as it always contains two digits when starting with 32. The third block
contains the character as a string and the second format argument. Finally, a line feed is added at the end
of the line.
Output of PrintAsciiTable

Dec Hex Dec Hex Dec Hex Dec Hex Dec Hex Dec Hex
32 20 48 30 0 64 40 @ 80 50 P 96 60 ' 112 70 p
33 21 ! 49 31 1 65 41 A 81 51 Q 97 61 a 113 71 q
34 22 " 50 32 2 66 42 B 82 52 R 98 62 b 114 72 r
35 23 # 51 33 3 67 43 C 83 53 S 99 63 c 115 73 s
36 24 $ 52 34 4 68 44 D 84 54 T 100 64 d 116 74 t
37 25 % 53 35 5 69 45 E 85 55 U 101 65 e 117 75 u
38 26 & 54 36 6 70 46 F 86 56 V 102 66 f 118 76 v
39 27 ' 55 37 7 71 47 G 87 57 W 103 67 g 119 77 w
40 28 ( 56 38 8 72 48 H 88 58 X 104 68 h 120 78 x
41 29 ) 57 39 9 73 49 I 89 59 Y 105 69 i 121 79 y
42 2A * 58 3A : 74 4A J 90 5A Z 106 6A j 122 7A z
43 2B + 59 3B ; 75 4B K 91 5B [ 107 6B k 123 7B {
44 2C , 60 3C <    76 4C L 92 5C \ 108 6C l 124 7C |
45 2D ‑ 61 3D =    77 4D M 93 5D ] 109 6D m 125 7D }
46 2E . 62 3E >    78 4E N 94 5E ^   110 6E n 126 7E ~
47 2F / 63 3F ?     79 4F O 95 5F _   111 6F o 127 7F DEL

Aligned Outputs
com/tutego/exercise/string/PaidOrNotPaid.java

public static void printList( String[] names, boolean[] paid ) {

if ( names.length != paid.length )
throw new IllegalArgumentException(
"Number of names and paid entries are not the same, but "
+ names.length + " and " + paid.length );

int maxColumnLength = 0;
for ( String name : names )
maxColumnLength = Math.max( maxColumnLength, name.length() );

String format = "%‑" + maxColumnLength + "s %spaid%n";

for ( int i = 0; i < names.length; i++ )


System.out.printf( format, names[ i ], paid[ i ] ? "" : "not " );
}

First, the method checks if the two arrays have an equal number of elements, and if not, an
IllegalArgumentException is thrown. Accessing length generates the desired
NullPointerException if the arrays are null.
Since it is unknown in advance how wide the first left column will be, we have to go over all the
strings and determine the maximum length. Using this maximum maxColumnLength we can build a
format string. The format string gets a format specifier that determines the width of a string, padded with
spaces. The format string has a leading minus sign, so this gives a left‑aligned string that is padded on the
18 Java Programming Exercises

right with spaces up to the maximum length maxColumnLength. In addition, the format string contains
a space to the right column of four spaces.
The right column contains either “paid” or “not paid”. That is, the string “paid” always occurs,
and only the word “not” is to be set dependent on a boolean value. This is done by the condition opera‑
tor, which either returns an empty string or the string “not” as a format argument for the format string.

Quiz: Define Regex


com/tutego/exercise/string/RegexExamples.java

// A string of exactly 10 digits

var p1 = Pattern.compile( "\\d{10}" );


out.println( p1.matcher( "0123456789" ).matches() ); // true
out.println( p1.matcher( "1" ).matches() ); // false
out.println( p1.matcher( "sauma ovo" ).matches() ); // false

// A string of 5 to 10 numbers and letters.

var p2 = Pattern.compile( "\\w{5,10}" );


out.println( p2.matcher( "01234567" ).matches() ); // true
out.println( p2.matcher( "0" ).matches() ); // false
out.println( p2.matcher( "01234567890123" ).matches() ); // false

// A string that ends with `.`, `!` or `?`, like a sentence.

var p3 = Pattern.compile( ".*[.!?]$" );


out.println( p3.matcher( "jes? jes!" ).matches() ); // true
out.println( p3.matcher( "ne?" ).matches() ); // true
out.println( p3.matcher( "okej." ).matches() ); // true
out.println( p3.matcher( "se vi diras tion" ).matches() );// false

// A string that contains no digits.

var p4 = Pattern.compile( "\\D*" );


out.println( p4.matcher( "Ciao" ).matches() ); // true
out.println( p4.matcher( "Cia0" ).matches() ); // false
out.println( p4.matcher( "" ).matches() ); // true

// Contains an official title, Prof., Dr., Dr. med., Dr. h.c.

var p5 = Pattern.compile( "(Prof\\.|Dr\\. med\\.|Dr\\. h\\.c\\.|Dr\\.)\\s" );


out.println( p5.matcher( "Saluton Sinjoro Dr. Miles" ).find() ); // true
out.println( p5.matcher( "ne korekta Dr. h.c. Thai med." ).find() );// true
out.println( p5.matcher( "Megan Dr.Thai" ).find() ); // false

In the last example, it is about finding and not about a complete match, so the find() method of Matcher
is used. In principle, tests of existence can also be formulated by .*FIND.* and matches(…), but match‑
ing makes a little more work for the regex engine than just providing the first find and not having to look
to the end.
1 • Advanced String Processing 19

Determine Popularity in Social Media


com/tutego/exercise/string/Popularity.java

String text = """


Make me a baby #CaptainCiaoCiao
Hey @CaptainCiaoCiao, where is the recruitment test?
What is a hacker's favorite pop group? The Black IP's.""";

var pattern = Pattern.compile( "[#@]CaptainCiaoCiao" );


System.out.println( pattern.matcher( text ).results().count() );

The task can be solved with a one‑liner because the Matcher method results() returns a
Stream<MatchResult>, and for Stream objects the count() method determines the number of
occurrences.

Detect Scanned Values


com/tutego/exercise/string/OcrNumbers.java

private final static String[] searches = {


"000", "11", "22", "333", "44", "55555", "6", "77777", "888", "9999" };

private static int parseOcrNumbers( String string ) {


String line = new Scanner( string ).nextLine().replaceAll( "\\s+", "" );

for ( int i = 0; i < searches.length; i++ )


line = line.replaceAll( searches[ i ], "" + i );

return Integer.parseInt( line );


}

If we take a closer look at the big numbers, we quickly realize that each large number contains the actual
number itself. The large zero contains 0, the large one contains 1, and so on. So, we don’t have to evaluate
several lines, it’s enough to take any line. We just take the first one.
After extracting the first line, we can search for the substring that makes up the single digits. The
blanks interfere a bit, so they are removed in the first step. A new String is created from the first line,
in which all spaces have been removed, and then the digits of each major character are aligned. For
example, if the line starts with 000, we know that the first digit in the result must be 0. We can simply
use replaceAll(…) to replace the sequence 000 with 0. For example, if there are two zeros in a row,
0000 correctly becomes 00.
Since not only three zeros have to be replaced by zero, but also two ones by a one, and there are ten
different replacements, we store the individual strings in an array beforehand. A loop runs through the
array, and in the body, there are repeated calls to replaceAll(…), which replaces all partial strings
from the search with the loop index, so that, for example, 000 becomes "" + 0, i.e., "0". At the end, we
convert the number to an integer and return the result.
If the incoming string is null, empty, or contains foreign characters, there will be exceptions in the
following. This behavior is fine.
20 Java Programming Exercises

Quiet Please! Defuse Shouting Texts


com/tutego/exercise/string/DoNotShout.java

public static String silentShoutingWords( String string ) {


return Pattern.compile( "\\p{javaUpperCase}{3,}" )
.matcher( string )
.replaceAll( matchResult ‑> matchResult.group().toLowerCase() );
}

The proposed solution proceeds in three steps: Building the pattern object, matching the string, and
replacing the match group with lowercase strings. The regex string must describe a sequence of uppercase
letters. Upper case letters, over the entire Unicode alphabet, determine \p{javaUpperCase}. We want
to have at least three uppercase letters in a row, which {3,} takes care of. Whether to keep the pattern
precompiled in a static variable depends entirely on how often the method is called. In general, it is a good
strategy to keep the Pattern objects in memory because translation always costs a little execution time.
On the other hand, you reference an object, and if you rarely need it, you don’t have to.
The method compile(…) gives us a Pattern object, and the matcher(…) method gives us a
Matcher object. We can well use the replaceAll(Function<MatchResult, String>) method,
which can perform a transformation of the found strings. The argument passed is a function that maps a
MatchResult to a string. Our function accesses the group, converts the string to lowercase, and returns
it. replaceAll(…) finds all places with the selected uppercase letters and calls this function mul‑
tiple times.

Converting Time from AM/PM


Format to 24‑Hour Format
com/tutego/exercise/string/AmPmToMilitaryTime.java

private static final Pattern AM_PM_PATTERN =


Pattern.compile( "(?<hours>\\d\\d?)" + // hours
"(?::(?<minutes>\\d\\d))?" + // minutes
"\\s?" + // optional whitespace
"(?<ampm>[ap])[.]?m[.]?", // AM/PM
Pattern.CASE_INSENSITIVE );

public static String convertToMilitaryTime( String string ) {


Matcher matcher = AM_PM_PATTERN.matcher( string );
return matcher.replaceAll( matchResult ‑> {
int hours = Integer.parseInt( matcher.group( "hours" ) );
int minutes = matcher.group( "minutes" ) == null ?
0 :
Integer.parseInt( matcher.group( "minutes" ) );
boolean isTimeInPm = "pP".contains( matcher.group( "ampm" ) );
if ( isTimeInPm && hours < 12 ) hours += 12;
else if ( !isTimeInPm && hours == 12 ) hours ‑= 12;
return String.format("%02d%02d", hours, minutes);
} );
}
1 • Advanced String Processing 21

At the heart of the program is a regular expression that captures times. This regular expression consists of
four parts, which are also split into four lines in the code. The first part captures the hours, the part cap‑
tures the minutes, the third part is an optional white space between the time, and the last part, AM/PM.

1. The hours consist of at least one integer, the second integer being optional if, for example, 1
AM is written. In principle, we could write the expression a bit more precisely so that something
like 99 AM is not recognized, but we do not make that check here. The hours themselves are in
round brackets, a group named ?<hours>. All regular expression groups can be named so that
we can access them more easily later by that name and not have to use a group index.
2. The minute’s part is optional, that is, it is enclosed in round brackets altogether, and there is a
question mark at the end. The inside starts with a ?:, which is a small regular expression opti‑
mization so that this group is inaccessible via the API later. If hours and minutes are specified
at the same time, a colon separates them. The minutes themselves are also a named group, and
they consist of two decimal numbers. Again, we do not make any checks about possible ranges
of validity.
3. The third part is a white space, which is optional.
4. The last part must capture different notations of AM/PM. A dot could be placed between the
two symbols, perhaps even mistakenly just after a letter, so say A.M or AM. So that we don’t
have to specify case, we include a special pattern flag that checks case independently, so it
doesn’t matter whether we write AM, am, Am, or pM.

The convertToMilitaryTime(String) method gets the string with the time information as a
parameter. The Pattern object was stored as a constant, and the matcher(…) method connects the
Pattern with the string method parameter. The result is a Matcher. This type can do all the work
with replaceAll(Function<MatchResult, String> replacer): the method runs over all the
matches for us, calls our Function, and we can access the match from the MatchResult and replace
it with a string.
Regarding the Function: first, we access the group for the hours and convert it to an integer.
Converting an integer will not throw an exception because our regular expression ensures that only digits
occur. The peculiarity with minutes is that they can be missing. So, we have to go back to the group min‑
ute and ask if it exists at all. If it does not exist, we assign the variable minutes with 0; otherwise, we
convert the string with the minutes into an integer and set the variable minutes with it.
Now we evaluate the group ampm and declare a variable isTimeInPm, which becomes true if the
time is given in PM. For AM, the variable remains false. This variable helps with the conversion. If
isTimeInPm is true, then the time is “post meridiem”, i.e., afternoon, and 12 hours must be added. It
may happen that the text mistakenly enters 23 PM, for example; in this case, we want to correct the error
and do not add 12. Moreover, if the time of the hours is equal to 12 o`clock, we also do not correct. The
next check is specifically for 12:xx, which becomes 00xx clock. So, if isTimeInPm equals false,
then it is the time “ante meridiem”, that is the morning, and we subtract 12.
After the two variables hours and minutes are set, we generate a string with the hours and min‑
utes and use String.format(…) so that we get the times with only one digit padded with a 0. This is
the return of the Function.

Split Address Lines with the StringTokenizer


com/tutego/exercise/string/SplitAddressLines.java

// String address = "Boots and Bootles\n21 Pickle Street\r\n424242 Douglas\


rArendelle";
String address="Doofenshmirtz Evil Inc.\nStrudelkuschel 4427\nGimmelshtump";
22 Java Programming Exercises

StringTokenizer lines = new StringTokenizer( address, "\n\r" );


String name = lines.nextToken();
String street = lines.nextToken();
String city = lines.nextToken();
final String DEFAULT_COUNTRY = "Drusselstein";
String country = lines.hasMoreTokens() ? lines.nextToken() : DEFAULT_COUNTRY;

System.out.println( name + ";" + street + ";" + city + ";" + country );

In the center of the job is the class StringTokenizer, which is useful whenever.

1. Not (all) tokens are to be extracted in advance like with split(…), but step by step.
2. The separators consist of single characters, but no strings.

Similarly, we create an instance of StringTokenizer, but it’s important to note that the two specified
characters are not treated as a combined separator; instead, they are considered as individual characters
that can serve as a separator for the tokens in any combination.
With the method nextToken() we ask for the lines three times, and since we don’t know if there is
a fourth line, we look ahead with hasMoreTokens(). If there is a token, we consume it. Otherwise, we
choose the desired default country.
Since StringTokenizer is an Enumeration<Object>, in principle we could have used
hasMoreElements() and nextElement(), but the latter method has the awkward Object return
type.

Split Sentences into Words and Reverse Them


Let’s start with a small helper method that prints words reversed:
com/tutego/exercise/string/PrintReverseWords.java

private static void printWordReversed( String word ) {


System.out.print( new StringBuilder( word ).reverse() );
System.out.print( ' ' );
}

The reversing of the string is done by the reverse(…)‑ method of the StringBuilder. We then out‑
put the result to the screen, separated by a space at the end.
Now we have to split the sentence and recognize the words.
com/tutego/exercise/string/PrintReverseWords.java

String string = "erehW did eht etarip esahcrup sih kooh? tA eht dnah‑dnoces pohs!";

String pattern = "[\\p{Punct}\\s]+";

new Scanner( string )


.useDelimiter( pattern )
.forEachRemaining( PrintReverseWords::printWordReversed );

System.out.println();

for ( String word : string.split( pattern ) )


printWordReversed( word );
1 • Advanced String Processing 23

At the center is the regular expression [\p{punct}\s]+. It captures a sequence of punctuation marks,
parentheses, etc., and white space separating words. We make use of predefined character classes. It uses
\p{punct} for a character out of

!"#$%&'()*+,‑./:;<=>?@[\]^_'{|}~

and \s for the white space; it is the character class [ \t\n\x0B\f\r]. For a connection, we put both
into a new character class, and since characters can occur any number of times in a row, we add a plus.
Java supports splitting with regular expressions via the Pattern‑Matcher combination, and two
well‑known facades are the Scanner and the split(…) method. Both variants are shown in the pro‑
posed solution. The Scanner is always good if the number of matches can be large because with the
split(…) method the answer is always an array with all words. The Scanner implements Iterable
and at forEachRemaining(…) we put a method reference to the helper method printWordRe‑
versed(…) for the Consumer, which writes each word reversed on the screen.

Check Relations between Numbers


com/tutego/exercise/string/RelationChecker.java

private static boolean isValidRelation( int number1, String operator,


int number2 ) {
return switch ( operator ) {
case ">" ‑> number1 > number2;
case "<" ‑> number1 < number2;
case "=" ‑> number1 == number2;
default ‑> false;
};
}

public static boolean isValidRelation( String string ) {


Scanner scanner = new Scanner( string );
int number1 = scanner.nextInt();

while ( scanner.hasNext() ) {
String operator = scanner.next();
int number2 = scanner.nextInt();
if ( isValidRelation( number1, operator, number2 ) )
number1 = number2;
else
return false;
}

return true;
}

The actual method checkRelation(String) gets the string and checks the relations. However, the
method falls back on its own private method isValidRelation(int, String, int) so we want
to start with that. isValidRelation(…) gets a number, a comparison operator, and another number. It
checks if the comparison operator with the two numbers returns a true result. If so, the answer is true; if
the comparison is false, the answer is false just as in the case of a misplaced symbol because we evalu‑
ate only <, > and =.
24 Java Programming Exercises

The method checkRelation(…) builds a Scanner with the passed String and now uses a
combination of nextInt(), hasNext(), and next() to process tokens from the Scanner. At the
beginning, there must always be a number, which means we can initialize a variable number1 with the
first number. The data stream could be empty now, but if the Scanner has the next symbols, this will be
a comparison operator, which we will refer to. After the comparison operator comes to a second integer,
which we also read in and store in number2. Now we call our method isValidRelation(…), and this
method returns true if the comparison was fine. Then number2 will become the new number1, so in
the next loop pass, number2 will be assigned the following number. If isValidRelation(…) returns
false, then we can abort the method because at this point the comparison is false. If there was no break‑
out from the loop, all comparisons were correct, and the method ends with return true.

Convert A1 Notation to Columns and Rows


com/tutego/exercise/string/A1Notation.java

private static final int NUMBER_OF_LETTERS = 26;

private static int parseColumnIndex( String string ) {


int result = 0;
for ( int i = 0; i < string.length(); i++ ) {
// Map A..Z to 1..26
int val = Character.getNumericValue( string.charAt( i ) ) ‑ 9;
result = NUMBER_OF_LETTERS * result + val;
}
return result;
}

public static int[] parseA1Notation( String cell ) {


Matcher matcher = Pattern.compile( "([A‑Z]+)(\\d+)" ).matcher( cell );
if ( ! matcher.find() || matcher.groupCount() != 2 )
return new int[]{ 0, 0 };
int column = parseColumnIndex( matcher.group( 1 ) );
int row = Integer.parseInt( matcher.group( 2 ) );
return new int[]{ column, row };
}

Let us consider the cell AA34 mentioned in the task as an example. In the first step, we need to separate
the column from the row. The column here would be AA, the row 34. We then need to convert the column
AA to the numeric representation, 27. Two separate methods handle these two steps. The main method
parseA1Notation(String) first extracts the row and column, and then calls an internal method
parseColumnIndex(String), which converts the column to a numeric value for us after the A1
notation.
Let’s start with the parseColumnIndex(String) method. We’ll take a few examples to make it
easier to read the calculation pattern.
What we can read is the following:

• Each letter is transferred to a number—A to 1, B to 2 until finally Z to 26.


• The example is a place value system. It is similar to our decimal system, but here the factor 26
is used as a multiplier.
1 • Advanced String Processing 25

TABLE 1.2 Calculation of A1 notation


SYMBOL SEQUENCE CALCULATION RESULT
A 1 × 260   1
Z 26 × 260 26
AA 1 × 261 + 1 × 260 27
IV 9 × 261 + 22 × 260 256
AAA 1 × 262 + 1 × 261 + 1 × 260 703

To convert the whole thing now into an algorithm, we use the Horner scheme. Let us illustrate this with
an example:

WDE = 23 × 262 + 4 × 261 + 5 × 260 = ((23 × 26) + 4) × 26 + 5

The Horner scheme is important for us because we don’t need to calculate powers anymore. If we go one
place further to the right, we multiply the old result by 26 and repeat the scheme for the other places. This
is precisely what the method parseColumnIndex(String) does. A loop runs over all characters,
extracts them, and queries the numeric representation with Character.getNumericValue(char).
This is defined not only for digits but also for letters. For the letter 'a' the result is 10, the same as for
'A'. For 'Z' it is 35. If we subtract 9 from this, we get the range of values 1–26. We take the old result,
multiply it by 26, and add the numeric representation of the letter. The next step is to calculate the new
numeric value of the next character, multiply the last result by 26, and again add the value of the last letter.
This performs the calculation exactly as we planned it.
The method parseA1Notation(String) has little work to do. First, we compile a Pattern that
extracts the column and row—since the column is all letters and the row is all digits, we can easily capture
that via the groups in the regular expression. If the string is wrong, and if we don’t have two matches, we
return an array of {0, 0}, signaling incorrect input. If there are two match groups, we take the column
information from the first one and convert it to an integer using our own parseColumnIndex(String)
method. The second string, according to the regular expression, is a valid string of digits, which Integer.
parseInt(String) converts to an int. The numeric column and row go into a small array, and that
goes back to the caller.

Parse Simple CSV Files with Coordinates


com/tutego/exercise/string/GenerateSvgFromCsvCoordinates.java

String filename = "coordinates.csv";


try ( InputStream is =
GenerateSvgFromCsvCoordinates.class.getResourceAsStream( filename );
Scanner scanner = new Scanner( is, StandardCharsets.ISO_8859_1 ) ) {
scanner.useDelimiter( ",|\\s+" ).useLocale( Locale.ENGLISH );

StringBuilder svg = new StringBuilder( 1024 );


svg.append( "<svg height=\"210\" width=\"500\">\n<polygon points=\"" );

while ( scanner.hasNextDouble() ) {
double x = scanner.nextDouble();

if ( ! scanner.hasNextDouble() )
throw new IllegalStateException( "Missing second coordinate" );
26 Java Programming Exercises

double y = scanner.nextDouble();
svg.append( x ).append( "," ).append( y ).append( " " );
}

svg.append( "\" style=\"fill:lime;stroke:purple;stroke‑width:1\" />\n</svg>" );


System.out.println( svg );
}

The file consists of sequences of integers separated by either a semicolon or a newline, generally speaking
by arbitrary white space. We need to find a tokenizer that we can feed with a regular expression that stands
for just these separators. Since we want to read from a file and process that with regular expressions, the
class Scanner is a good choice. This is also how the proposed solution does it.
The Scanner is connected to an input stream, the file we would like to read. The character encoding
is explicitly set to UTF‑8.
Then the Scanner is initialized with a regular expression for the delimiters. These delimiters are
set by the Scanner method useDelimiter(…). It is important to set the Locale.ENGLISH because
by default the Scanner is preconfigured with the Locale by the operating system, and if that is, for
example, German, the Scanner expects floating‑point numbers with a comma as separator. But the
source always has English formatted numbers.
After the Scanner is prepared, the program can produce the output. It starts with the SVG container
and the polygon start tag. The Scanner method hasNext() helps to iterate through the file. When the
hasNext() method returns a token, we always expect pairs. We can read the first integer, and now there
must be a second integer. But if the Scanner cannot give a new token, this is an error, and we raise an
exception. If the second number exists, it will also be read in. The pair can then be placed in the SVG
container.
At the end of the loop, we close the polygon tag and print the SVG element to the screen. For the
output, we don’t need to pay attention to the language for append(double) because the formatting of
the double is automatically in English.

Compress Strings Lossless by Runlength Encoding


com/tutego/exercise/string/SimpleStringCompressor.java

public static String compress( String string ) {

if ( string.isEmpty() )

return "";

char lastChar = string.charAt( 0 );


int count = 1;
StringBuilder result = new StringBuilder( string.length() );

for ( int i = 1; i < string.length(); i++ ) {


char currentChar = string.charAt( i );
if ( currentChar == lastChar )
count++;
else {
result.append( lastChar );
if ( count > 1 )
result.append( count );
count = 1;
1 • Advanced String Processing 27

lastChar = currentChar;
}
}

result.append( lastChar );
if ( count > 1 )
result.append( count );

return result.toString();
}

private static CharSequence decodeToken( String token ) {

if ( token.isEmpty() )
return "";

if ( token.length() == 1 )
return token;

int length = Integer.parseInt( token.substring( 1 ) );


return String.valueOf( token.charAt( 0 ) ).repeat( Math.max( 0, length ) );
}

public static String decompress( String string ) {


StringBuilder result = new StringBuilder( string.length() * 2 );
Matcher pattern = Pattern.compile( "[.‑](\\d*)" ).matcher( string );

while ( pattern.find() )
result.append( decodeToken( pattern.group() ) );

return result.toString();
}

In the first step, we want to compress the string. To achieve this, we first query whether the string contains
any text at all; if not, we are quickly done with the task.
To see how many of the same characters occur in the text in a row, we use a variable lastChar for
the last character seen so that we can compare a new character with the last character. In addition, we
note the number of same characters in count. Since this result is freshly built, we add a variable result
of the data type StringBuilder.
The for loop goes over each character and stores it in the auxiliary variable currentChar. Now,
two things can happen: The character currentChar just read can be the same as the previous character
in lastChar, or it can be a different character. We have to handle this difference.
The initial check determines if the previously observed character matches the currently read char‑
acter. If it’s a match, we simply increase the counter and continue the loop. However, if the newly read
character differs from the previous one, the local compression process concludes. We begin by writing
this character to the buffer. Then, we address the count: if more than one identical character was previ‑
ously counted, we input that count into the data stream. But if there was just one character, we don’t add
1 to the buffer, in accordance with the task’s instructions. After finalizing the character‑counter pair, it’s
essential to reset the counter to 1. We are almost done with the loop. The moment a new character is found,
we set lastChar to exactly the current character currentChar.
When we are done with the loop, we still have a character in lastChar and count. We therefore
perform the same query as before in the case distinction, and append the counter to the string if the coun‑
ter is greater than 1.
28 Java Programming Exercises

In the method for unpacking, we fall back on the pattern that results from the compression. There
are always pairs of a string and a number, with the special case that the pair is single, and the number
is missing. Using a regular expression, we run the entire string and look at all the pairs. To keep the
method from getting too big, we use a helper method called decodeToken(String) that takes a pair
and expands it.
First, the method must find out whether the token consists of only one character or of several charac‑
ters. If the string consists of only one character, then it must have been our symbol, and it comes into the
output. If the string is longer than 1, then there is a length encoding from the second position upward. With
substring(1) we extract the string and convert it to an integer, so that the repeat(int) method of
String can generate us exactly this number of characters token.charAt(0). With substring(1)
we extract the string and convert it to an integer, so that the repeat(int) method of String can gener‑
ate us exactly this number of characters token.charAt(0).

Quiz: Encoding for Unicode Characters


When we write a string in source code, we don’t worry much about encoding because we can write numer‑
ous characters directly in quotes. But when these strings are written to a file, for example, the encoding is
relevant because other parties will naturally want to read that file again.
Unicode’s characters require four bytes in their full extent. However, this is a waste if the character
can only be encoded in one byte, such as a simple ASCII character. Therefore, one encodes Unicode char‑
acters to get the shortest possible representation. Common encodings are UTF‑8 and UTF‑16; they can
represent all Unicode characters. This is not true for Latin‑1, for example, because Latin‑1 is only eight
bytes, and hundreds of thousands of characters cannot be represented in Latin‑1. UTF‑8 encoding will use
one byte if possible, then use two bytes if possible, otherwise use three or four.

Quiz: Order of Strings with and without Collator


The outputs are:
com/tutego/exercise/string/CollatorDemo.java

Comparator<String> comparator = Comparator.naturalOrder();


System.out.println( comparator.compare( "a", "ä" ) ); // < 0
System.out.println( comparator.compare( "ä", "z" ) ); // > 0 !!
System.out.println( comparator.compare( "n", "ñ" ) ); // < 0
System.out.println( comparator.compare( "ñ", "o" ) ); // > 0 !!

Comparator<Object> collatorDE = Collator.getInstance( Locale.GERMAN );


System.out.println( collatorDE.compare( "a", "ä" ) ); // < 0
System.out.println( collatorDE.compare( "ä", "z" ) ); // < 0
System.out.println( collatorDE.compare( "n", "ñ" ) ); // < 0
System.out.println( collatorDE.compare( "ñ", "o" ) ); // < 0

TABLE 1.3 Bit assignments of UTF8 encoding


NUMBER OF FIRST CODE LAST CODE
BYTES BITS POINT POINT BYTE 1 BYTE 2 BYTE 3 BYTE 4
1 7 U+0000 U+007F 0*******
2 11 U+0080 U+07FF 110***** 10******
3 16 U+0800 U+FFFF 1110**** 10****** 10******
1 • Advanced String Processing 29

TABLE 1.4 Some characters with their positions in the Unicode standard
CHARACTER θ A a Ä ß ä ñ
Code point (decimal) 48 65 97 196 223 228 241

The natural ordering of strings is lexicographic, meaning that the position of the character in the Unicode
alphabet counts. Let’s illustrate this with some characters.
From the table, you can see that the digits are first, followed by the uppercase letters and then the
lowercase letters. The umlauts are far behind the capital letters and not sorted between the upper and
lower case letters.
Umlauts are regular letters in German, which do not come after “Z” in the order. The standard DIN
5007‑1 describes under “Ordering of character sequences (ABC rules)” two sorting procedures:
DIN 5007, variant 1 (used for words, for example, in dictionaries)

• “ä” and “a” are the same.


• “ö” and “o” are the same.
• “ü” and “u” are the same.
• “ß” and “ss” are the same,

DIN 5007, variant 2 (special sorting for lists of names, such as in telephone directories)

• “ä” and “ae” are the same.


• “ö” and “oe” are the same.
• “ü” and “ue” are the same.
• “ß” and “ss” are the same.

There are similar rules for other languages. The lexicographical order does not support this. Therefore,
the Unicode Collation Algorithm describes how the sorting looks like in different national languages. For
an introduction, see also https://en.wikipedia.org/wiki/Unicode_collation_algorithm.
In Java Collator objects are available. They are initialized with a Locale object. In addition
to the language, so‑called levels can be passed; the Javadoc gives further examples under the heading
“Collator strength value”.
Mathematics
2
Integers and floating‑point numbers already appeared in the first exercises; we were using the common
mathematical operators to crunch numbers. But Java does not have an operator for everything, and so
the class Math offers further methods and constants; early on we used Math.random(), for example.
Throughout this chapter’s upcoming tasks, our focus will be on various rounding techniques, particularly
exploring the methods offered by the Math class. In addition, the java.math package provides two
classes that can be used to represent arbitrarily large numbers—there are tasks for these as well.
Prerequisites

• Know rounding methods of the class Math.


• Know BigInteger and BigDecimal.

Data types used in this chapter:

• java.lang.Math
• java.math.BigInteger
• java.math.BigDecimal

THE CLASS MATH


The class Math contains numerous mathematical functions. It is also important to look at wrapper classes,
for example, or at the Scanner or Formatter when it comes to converting a number to a string or pars‑
ing a string so that there is a primitive type at the end again.

Quiz: Rule of Thumb ⭑


There are different approaches and different kinds of problems for rounding numerical values:

• On the one hand, a floating‑point number can be converted to an integer.


• On the other hand, the number of decimal places can be reduced for a floating‑point number.

The Java library supports different possibilities for conversion and rounding, among other things with

• The explicit type conversion (int) double → int.


• Math.floor(double) → double.
• Math.ceil(double) → double.
• Math.round(double) → long.

30 DOI: 10.1201/9781003495550-3


2 • Mathematics 31

• Math.rint(double) → double.
• BigDecimal and setScale(..) → BigDecimal.
• NumberFormat, configured with setMaximumFractionDigits(…), then format(…)
→ String.
• DecimalFormat, configured with setRoundingMode(…), then format(…) → String.
• Formatter with a format string, then format(…) → String.

Four of the methods originate from Math, but when it comes to gigantic and precise floating‑point num‑
bers or string representation, other classes are involved. Since the methods differ slightly in the result, the
following task should make these differences clear once again.
Task:

• Fill in the following table with the results of the roundings:

DOUBLE (INT) (INT) (INT)


VALUE D (INT) D FLOOR(D) CEIL(D) ROUND(D) RINT(D)

-2.5
-1.9
-1.6
-1.5
-1.1
1.1
1.5
1.6
1.9
2.5

Check If Tin Tin Cheated on Rounding ⭑


The accountant Tin Tin does the accounting for Captain CiaoCiao of income and expenses. She gets posi‑
tive and negative floating‑point values and writes down the total as a rounded integer for a summary at
the end. Captain CiaoCiao suspects that Tin Tin is not being completely honest and is pocketing the penny
amounts when she should use commercially rounding. As a reminder, if the number at the first omitted
decimal place is a 0, 1, 2, 3, or 4, round down; if it is 5, 6, 7, 8, or 9, round up.
To test his guess, Captain CiaoCiao needs a program that can sum and check different rounding
modes.
Task:

• Given an array of floating‑point numbers (positive and negative) and the sum converted to an
integer by Tin Tin.
• Captain CiaoCiao wants to find out which rounding was used to form the integer of the sum.
Therefore, the elements in the array are to be summed and compared to Tin Tin’s sum. The
rounding is done after the numbers are added.
• Implement a method RoundingMode detectRoundingMode(double[] numbers,
int sum) that gets a double array of numbers and the sum of Tin Tin and checks which
rounding mode was used.
• To allow the rounding mode to be represented, introduce an enumeration type:
enum RoundingMode {
CAST, ROUND, FLOOR, CEIL, RINT, UNKNOWN;
}
32 Java Programming Exercises

• The enumeration elements represent different rounding modes:


• (int), that is, a type conversion.
• (int) Math.floor(double).
• (int) Math.ceil(double).
• (int) Math.rint(double).
• (int) Math.round(double).

• Which rounding is bad for Captain CiaoCiao and good for Tin Tin? Which variation could Tin
Tin use to cheat?

Example:

• The call might look like this:


double[] numbers = { 199.99 };
System.out.println( detectRoundingMode( numbers, 200 ) );

Notes:

• There is an enumeration type RoundingMode in the java.math package, but for our case,
it does not fit the task.
• It may well happen that more than one rounding mode fits—such as when the sum of the
­floating‑point values itself gives an integer—then the method is free to choose one of the round‑
ing modes.

HUGE AND VERY PRECISE NUMBERS


The classes java.math.BigInteger and java.math.BigDecimal can be used to represent arbi‑
trarily large integer and floating‑point numbers.

Calculate Arithmetic Mean of a Large Integer ⭑


To calculate the arithmetic mean of two numbers, they are added together and divided by two. This works
well if the sum of the two values does not exceed the largest number that can be represented. If there is
an overflow, the result is wrong. Some algorithms in computer science can handle this problem as well,
but we can make it a little easier and take the higher data type in each case. For example, if we want to
calculate the mean value of two int variables, we convert the two int to a long, add the numbers,
divide, and convert back to the int. With the long data type, there is no larger primitive data type, but
the BigInteger type can be used well for the case.
Task:

• Calculate the arithmetic mean of two long values so that there is no overflow and wrong
results. The result should be a long again.
2 • Mathematics 33

Number by Number over the Phone ⭑


A new deal has made Bonny Brain a lot of money. The number is so big that you can’t just announce it
over the phone at all; it has to be conveyed in chunks.

Task:

• Write a new method BigInteger completeNumber(int... parts) that gets a vari‑


able number of numbers and returns the big total number at the end.

Example:

• completeNumber(123, 22, 989, 77, 9) returns a BigInteger with the value


12322989779.
34 Java Programming Exercises

Develop Class for Fractions and Truncate Fractions ⭑⭑


Bonny Brain is trying a new recipe for a rum punch. Fractions like “1/4 liter grape juice” or “1/2 liter rum”
keep appearing in the directions for making it. For the party, she prepares 100 servings, and fractions like
“100/4 liters” occur. The fractions can be shortened so that Bonny Brain knows, for example, that 25 liters
of grape juice must be purchased.
Task:

1. Create a new class Fraction.


2. Let there be a constructor Fraction(int numerator, int denominator) that stores
numerator and denominator in public final variables.
• Consider whether there can be faulty arguments, which we should report through exceptions.
• Every created fraction should be simplified automatically. Use the gcd(…) method of
BigInteger, which calculates the greatest common divisor (gcd)_. Remember: the gcd
of numerator and denominator is the largest number by which both are divisible. You can
simplify the fraction by dividing both the numerator and denominator by this number.
• Both numerator and denominator can be negative, but then you can flip the sign so that both
values become positive.
• The objects are all supposed to be immutable, and therefore the variables can be public
since they are not supposed to be changed after initialization via the constructor. In other
words, the class Fraction does not contain any setters.
3. Add the constructor Fraction(int value), where the denominator automatically becomes 1.
4. Implement a method to multiply fractions and detect overflows.
5. Implement a method reciprocal() that returns the inverse of a fraction, that is, swaps
the numerator and denominator. Thanks to this method, the division of fractions can be
implemented.
6. Fraction shall extend java.lang.Number and implement all mandatory methods.
7. Fraction shall implement Comparable because fractions can be converted to a decimal
number, and decimal numbers have a natural order.
8. Fraction shall implement equals(…) and hashCode() correctly.
9. Implement a toString() method that returns a string as bare as possible.
2 • Mathematics 35

T
«interface»
Number
Comparable

«final»
Fraction

+numerator: int «final»


+denominator: int «final»
Operationen
+Fraction(numerator: int, denominator: int)
+Fraction(value: int)
+reciprocal(): Fraction
+multiply(other: Fraction): Fraction
Number
+intValue(): int
+longValue(): long
+doubleValue(): double
+floatValue(): float
Comparable
+compareTo(other: Fraction): int
Object
+equals(other: Object): boolean
+hashCode(): int
+toString(): String

FIGURE 2.1 UML diagram of Fraction.

SUGGESTED SOLUTIONS

Quiz: Rule of Thumb


TABLE 2.1 Different roundings of a floating‑point number d in comparison
(INT) (INT) (INT)
VALUE d (INT) d FLOOR(d) CEILING(d) ROUND(d) RINT(d)
‑2.5 ‑2 ‑3 ‑2 ‑2 ‑2
‑1.9 ‑1 ‑2 ‑1 ‑2 ‑2
‑1.6 ‑1 ‑2 ‑1 ‑2 ‑2
‑1.5 ‑1 ‑2 ‑1 ‑1 ‑2
‑1.1 ‑1 ‑2 ‑1 ‑1 ‑1
1.1 1 1 2 1 1
1.5 1 1 2 2 2
1.6 1 1 2 2 2
1.9 1 1 2 2 2
2.5 2 2 3 3 2
36 Java Programming Exercises

Math.round(double) and Math.rint(double) differ for .5 numbers “on the edge”:

• round(double) rounds commercially. As can be seen in the table, round(‑2.5),


round(‑1.5), round(1.5), and round(2.5) round up; the numbers always become larger.
If one always rounds up only commercially, this produces small errors because the procedure
is not symmetrical. To be fair, some .5 would also have to be rounded down; this is where
another method comes into play.
• rint(double) behaves like round(double) for numbers not ending in .5, but when end‑
ing in .5 the following rule applies: the last digit to be retained becomes even. This behavior
is called symmetric (also mathematical, scientific) rounding because it rounds up or down in
half the cases, respectively.

In summary:

TABLE 2.2 Rounding method


PROCEDURE RESULT
type conversion (int) d Truncates decimal places of a floating‑point number.
floor(d) Rounds to the next smaller number against −∞.
ceil(d) Rounds to the next larger number against +∞.
round(d) Rounds the value according to commercial rules.
rint(d) Rounds double values. symmetrically/
mathematically/scientifically.

Check If Tin Tin Cheated on Rounding


Now we come to the question of which rounding is bad for Captain CiaoCiao and good for Tin Tin. The
difference between the rounded value and the sum is the difference Tin Tin can pocket. Example: If the
total is 222.22 and Tin Tin rounds to 222, there is a difference of 0.22 that Captain CiaoCiao misses and
goes into Tin Tin’s pocket. What do the differences look like for the example numbers?

TABLE 2.3 Difference from rounding, sum in foot


VALUE d d ‑ (INT) d d ‑ FLOOR(d) d ‑ CEIL(d) d ‑ ROUND(d) d ‑ RINT(d)
−2.5 −0.5 0.5 −0.5 −0.5 −0.5
−1.9 −0.9 0.1 −0.9 0.1 0.1
−1.6 −0.6 0.4 −0.6 0.4 0.4
−1.5 −0.5 0.5 −0.5 −0.5 0.5
−1.1 −0.1 0.9 −0.1 −0.1 −0.1
1.1 0.1 0.1 −0.9 0.1 0.1
1.5 0.5 0.5 −0.5 −0.5 −0.5
1.6 0.6 0.6 −0.4 −0.4 −0.4
1.9 0.9 0.9 −0.1 −0.1 −0.1
2.5 0.5 0.5 −0.5 −0.5 0.5

We can read that for the numbers Tin Tin chose, she gets the most out of rounding off all the sums.
Rounding off makes the numbers smaller, and she gets the difference in each case, whether the numbers
are negative or positive.
Random documents with unrelated
content Scribd suggests to you:
CHAPTER XV
Making a Toy Auto Truck (Continued)
THE STARTING CRANK—THE STEERING WHEEL
AND COLUMN—MUD GUARDS AND
RUNNING BOARDS—LIGHTS, TOOL BOXES,
HORNS, ETC.—DRIVERS’ CABS

Various fittings may be added to the truck and these add very
much to the general appearance and make the truck very realistic.
The Starting Crank.—A starting crank may be made of a piece
of galvanized wire bent into a crank shape and placed in position
through holes punched for it in front of the frame and through an
extra piece soldered underneath the frame.
Cut a piece of galvanized wire about 5 inches in length. Fairly
heavy wire will look better than thin wire when made up into a
crank. Mark off 1 inch from one end of the wire and then make
another mark 1 inch in from this one. Place the wire in the vise jaws
so that the first mark is parallel with the top of the jaws. Use a
hammer to bend the wire over at right angles, then move the wire
up to the second mark and bend the wire again at right angles so as
to produce a crank form as shown in Fig. 79.
Use an ice pick to punch a hole in the front of the truck frame and
make it large enough so that the crank will turn in it freely.
Cut a piece of tin ¾ by ¾ inches and bend over ¼ inch at one
end and punch a hole to fit the crank wire in the center of the
largest side of this piece and solder it in position directly back of the
hole punched in the front of the frame and in such a position that
the end of the crank wire projects about ¼ inch beyond the small
angle piece soldered to the frame, as shown in Fig. 80.

Fig. 79. Fig. 80.

Fig. 81.

Wind a narrow strip of tin about the straight projecting end of the
crank wire and solder it in place, the solder being applied to the end
of the wire and to the end of the coiled strip of tin at the same time,
Fig. 81.
The Steering Wheel and Column.—A steering wheel may be
made of an old clock gear wheel with the teeth cut off, or a small
can lid may be used instead. The steering wheel column may be
made of a piece of heavy galvanized wire.
Clock gear wheels are usually fastened to a short steel shaft, but
they may be easily driven off the shaft by placing the shaft of the
wheel in the vise jaws so that the wheel is above the vise jaws, and
then a few light hammer blows directed at the upper end of the
shaft will loosen the wheel and it may be easily removed. The vise
jaws should hold the shaft very loosely as it is being driven out of
the wheel.
Use the metal shears to cut off the gear teeth and a smooth flat
file to file down the roughness left at the edge of the wheel.
Find a piece of galvanized wire that fits into the hole in the clock
wheel or file a larger piece down until it does fit. The wire should
project slightly beyond the wheel and be soldered to it in exactly the
same manner as the tin can wheel is soldered to an axle. The wire
that the steering gear is soldered to should be long enough to go
through the dash-board, hood and frame, if the wheel is to turn. A
strip of tin is coiled about the wire below the frame as shown in Fig.
82. These are soldered in place to the wire to keep it in position and
yet allow it to turn freely in the holes.
Mud Guards and Running Boards.—Mud guards may be made
from a part of the side and bottom of a can as shown in Fig. 83. A 3-
inch can is the best size to use for the truck. The can is cut down to
a height of 1⅛ inches and then cut into two parts across the bottom
so that two mud guards may be made from each can. The outer
edges are turned as in making a tray and folded pieces are slipped
over the ends as shown in Fig. 83. These mud guards are soldered
to the frame in the position shown.
Fig. 82.

Running boards may be made of two pieces of tin, each piece to


be cut 1¼ inches wide and as long as it is desired. The four pieces
are each turned down ⅛ inch at the long sides and two pieces are
fitted over each other to make one running board as shown in Fig.
84. Two or three supports may be made of galvanized wire for the
running boards. These supports extend across the frame of the truck
and one end of each support is soldered to each running board. One
end of each running board is usually soldered to each mud guard.

Fig. 83.
Lights, Horns, etc.—Headlights may be made of thumb tack
boxes, bottle caps or the tops of tooth powder cans. Sidelights may
be made from the screw caps of cooking oil cans or the cylindrical
part of tooth powder can tops.
Tail-lights may be made of the screw caps of cooking oil cans.
Searchlights may be made of the smallest size adhesive tape
boxes mounted on suitable standards made of galvanized wire or
strips of tin.

Fig. 84.

The central part of the cover of these boxes is cut away and a
piece of isinglass or transparent celluloid may be fitted in to look like
a lens. The central part is cut away by using a small chisel to cut
with when the cover is placed over the end of a round stick held in
the vise. The rough edges are smoothed away by using a smooth
half-round file.
The construction of these lights is so simple as to need no further
explanation and they are simply soldered to the frame or hood
where they touch it when placed in position. The searchlight is
usually mounted by punching a hole for the standard in the cowl, or
by soldering on an extra piece to the dash to receive the wire
standard, Fig. 85.
Fig. 85.

Tool Boxes, Horns, etc.—Small rectangular beef cube or


chewing gum boxes may be soldered to the running board for tool
boxes. These boxes have rounded corners and look very much like
the large tool boxes, Fig. 85.
Fig. 86.

Horns may be made in several ways, the simplest form being a


piece of tin rolled into a cone shape and soldered to the dash. A
more realistic horn may be made by soldering a screw cap to the
larger end of the cone and adding the cap of a paint tube to the
smaller end. A hand horn may be made as shown in Fig. 85.
Speedometers, voltmeters and ammeters may be made of screw
tops soldered inside the dash as shown.
Drivers’ Cabs.—Most of the large trucks have some kind of a cab
to protect the driver from the weather, excepting the army trucks,
which usually depend on part of the canvas hood or cover for
protection.
On the toy trucks these cabs may be very simply made from a
square tin cocoa or olive oil can or they may be more elaborately
built, depending on the ability of the maker. These cabs should be
carefully made and kept in proportion to the rest of the truck.
All sharp edges should be turned over or bound with folded strips
of tin. Windows may be cut in the cab by placing it on the block and
using a small chisel to cut them out. The edges of these windows
should all be bound with folded strips of tin as shown in the
illustration.
The buggy top for the driver’s seat may be made from part of a
certain well-known curved tobacco box and several short pieces of
galvanized wire, Fig. 86.
CHAPTER XVI
Boats
THE ROWBOAT—THE SAILBOAT—THE SCOW—
THE TUGBOAT—THE BATTLESHIP—THE
FERRY-BOAT

The elliptically shaped tin cans, used for fish of different kinds,
may be made up into boats that will float. A deck is soldered tightly
to the can where the lid has been removed and various
superstructures added to make the different types of boats, but to
form a rowboat, seats may be soldered to an open can.
The Rowboat.—The rowboat is the simplest one to make as no
deck is to be soldered on. A narrow elliptical fish can should be
used. These cans usually contain fresh mackerel, and are of real
boat shape.
Such cans are opened at the top inside the rolled rim. The extra
tin near the edge of rim should be broken away with the pliers as in
making a pail, all roughness being filed away.
Lay the can face down on a sheet of paper, drawing around the
outside edge with a sharp pencil to get an outline of the boat. This
outline will serve as a guide when cutting out the seats. The seats
may be cut to the outline of the boat already traced on paper, when
the two end seats will fit bow and stern. But the center seat will
have to be trimmed off a bit to fit the boat. The free edges of the
seats must be turned down as a finish.
The Sailboat.—A catboat or sloop may be made from the same
sort of narrow elliptical can or even of a wider can of the same
shape. A deck is soldered to this can, a hole cut in it for a cockpit. To
the edge of the cockpit a folded band of tin is soldered.
A tube of tin is soldered to the stern, and a wire tiller is run
through this tube and soldered to a rudder. A hole is punched in the
center of the forward deck, and a tube of tin is soldered in this hole
to contain the mast. The mast and spars are of wood.
The keel is made of a piece of tin soldered to the bottom of the
boat. The boat should be completed, and the mast, spars and sails
in place, before the keel is put on. Try the boat in a basin of water. It
will probably tip over unless a very broad can is used to make it. Cut
out a keel of the shape shown in Fig. 87 and solder it lightly in place
at each end. Place the boat in the water again to see how it floats. If
the keel is too heavy, part of it may be cut off, if it is too light, it may
be broken away and a heavier one made and soldered on. When
properly made these boats are good sailers.
When soldering a deck to the boat, the rough edge remaining
after cutting away the lid of the can is left in place so as to form a
sort of ledge to solder the deck to. The rough flutings may be
flattened out by using a pair of flat-nosed pliers to press down the
flutes as you work along and simply pinching it flat.
Fig. 87.

The Scow.—A small scow may be made from a biscuit box of flat
tin, the kind that has contained small sweet biscuits with a cream
filling. Both box and lid are used and cut down as indicated in Fig.
88. The box is left at the original width. The two ends are cut away
from the lid. The two folded-down sides of the lid are used to make
folded strips with which to bind the sides of the scow.
A tiny box made of part of the lid is soldered to the rear deck of
the scow for a cabin. A small piece of galvanized wire bent at an
angle is soldered to the cabin for a stovepipe. The towing bits are
rivets soldered to the forward deck.
The Tugboat.—Tugboats may be made from the larger elliptical
fish cans. A good sized can of this sort is that one commonly found
to contain kippered herring. This can will make up into a large
tugboat, but if a small tug is to be made to tow the scow previously
described, a mackerel roe can is the best to use.
A deck is soldered tightly to the can, as in making the sailboat,
except that the deck is left whole; no openings are cut in it.
The cabin is made from a rectangular cocoa can, or a small olive
oil can, cut down to a suitable height and soldered to the deck,
bottom up.

Fig. 88.
The pilot house is made from a small adhesive plaster box, the
smokestack being from a small piece of tin with top edge first folded
over and then rolled into a cylindrical shape. A piece of wire may be
soldered to the stack for an exhaust pipe. A tiny piece of wire is
soldered to the front of the stack for a whistle. These pieces of wire
may be tied to the stack with fine iron binding wire, such as florists
use. When the wire exhaust and whistle are soldered to the stack
the wire may then be removed. It will be found very difficult to
solder these short pieces in place without binding them in position.
PLATE XV

Courtesy Pictorial Review

Boats made by author

The lifeboat is made from a small folded piece of tin, both ends
being pushed in and soldered together. The finished boat is soldered
to the roof of the cabin.
The towing bits are rivets soldered to the deck. Remember to use
the pliers to hold the rivets in place when soldering them on. When
these boats are floated in the water they may be found to tip to one
side slightly. A bit of solder may be melted on to the bottom of the
boat with the copper in such a position that it will counteract any
tendency to tip.
The Battleship, Destroyers, etc.—The battleship shown in
Plate XV is made from a narrow elliptical fish can. A deck is soldered
on and a cabin made of a small rectangular box such as beef cubes
usually are packed in.
The turrets are made of pill or salve boxes of small round tin
design. The lid of the box is soldered to the deck and when the box
is set in the lid the turret may be turned about.
The guns are made of short pieces of wire soldered to the turrets
and cabin.
The mast is made of a tin oil can spout or a piece of tin rolled into
a cone shape. A screw cap of a tooth paste tube is soldered to it for
a fighting top.
Some sort of a keel will have to be soldered to the battleship to
keep it upright in the water. Three pieces of heavy galvanized wire
may be soldered to the bottom, one in the center and one at each
side, or a strip of sheet lead may be soldered to the bottom.
A destroyer may be built up in the same manner as the battleship;
in fact, almost any type of boat may be built by changing the
superstructure.
The Ferry-boat.—A ferry-boat may be built with paddle wheels
that will revolve when the boat is pulled along in the water or
anchored in a running stream.
The hull is made from a kippered herring can with a deck soldered
on. Four strips of tin are cut for the sides of the cabins. Two of these
are soldered to the sides of the hull next to the rolled rim and
following the outline of the can or hull. The two inside walls of the
cabins are soldered about ¾ of an inch inside the outer walls which
leaves a gangway through the center of the boat.
An upper deck is soldered to these four walls; the inner walls need
only be soldered to the upper deck at each end.
The two pilot houses are made of adhesive plaster boxes and the
smokestack is rolled up from a piece of tin.
A hole is punched or drilled through all four walls of the cabin to
receive the axle of the paddle wheels.
The paddle wheels are made from small cans exactly in the same
way as the auto truck wheels and eight small square pieces of tin
are soldered to the circumference of each wheel for paddles. Rolled
strips of tin are placed on the axles between the wheels and the
cabins for washers. The axle should revolve very freely in the axle
holes.
If one has some mechanical ability it is not very difficult to form a
crank in the paddle wheel axle and attach a connecting rod to a
small tin walking beam which will move up and down as the paddle
wheels revolve. An imitation piston rod may be fastened to the other
end of the walking beam and allowed to run free through a hole in
the upper deck.
The wheels of the ferry-boat will revolve if it is anchored in a
running stream or towed behind a rowboat.
CHAPTER XVII
A Toy Locomotive
A SIMPLE TOY LOCOMOTIVE—THE FRAME—
BOILER—CAB—WHEELS—CYLINDERS AND
CONNECTING RODS—THE SMOKESTACK,
STEAM DOME AND WHISTLE, SAND BOX
AND HEADLIGHT—CARS—A PASSENGER
CAR AND SOME OTHERS

The locomotive shown in Plate XV is made so that the connecting


rods move back and forth as the locomotive is pulled along. The
principal dimensions are given in Fig. 89. This locomotive is not
much more difficult to make than the auto truck, but it should not be
attempted until the auto truck is satisfactorily completed.
The Frame.—The frame of the locomotive should be made first,
and it is made from a flat piece of tin 5¼ by 10½ inches. Scribe a
line ¼ inch inside and along all edges, cut off the corners as shown
in Fig. 89 and fold all four edges in. Cut into the corners of the
frame on lines A, A, A, A.
PLATE XVI
Simple toy locomotive and sand or water mill made by
the author

The first tin can toy. A locomotive made by the author


for his son
PLATE XVII
Courtesy New York World

Steam tractor and gun unpainted


Turn down the two sides of the frame first, then turn down the
two ends. The four pieces of the sides that project beyond the sides
are turned in over the ends as shown in Fig. 89. The sides and ends
of the frame may be turned over a square maple block. Solder the
frame at the ends.
Fig. 89.

The Boiler.—The boiler is made of two small soup cans. One


whole can is used and the bottom and part of the sides of another
can of exactly the same size is soldered to the first can to make a
long boiler. One long can, if obtainable, may be used for the boiler.
When two or more cans are soldered together to make a long boiler
the two rolled rims of the cans soldered together give the
appearance of a boiler strap as shown in Fig. 89.
The Cab.—The cab is made of a rectangular cocoa can. Most of
one side is cut away leaving just enough to fold back against the
sides of the cab. The cab is then placed on a wooden block and a
chisel is used to cut the window openings. A large round punch may
be used to cut out the front windows or a very small chisel made of
a nail may be used to cut these circular windows.
A top is made for the cab from a piece of tin 3¾ by 3¾ inches
square. One-quarter inch is marked off and turned in all around this
piece. Two opposite sides are folded down and the two other sides
are left standing at right angles to the piece and these two opposite
sides are left open just enough to slide over the top of box forming
the cab where the top is soldered in place as shown in the drawing.
The boiler should be soldered to the cab and then these two are
soldered to the frame where they touch it at the front end of the
boiler and the base of the cab.
The Wheels.—The front wheels of the locomotive are made of
the small sized evaporated milk cans exactly in the same way that
the wheels of the auto truck are made. These wheels are 2½ inches
in diameter and ⅝ inch wide.
The wire axle of the front wheels passes through two lugs that are
soldered to the sides of the frame.
The driving wheels are made from 3½-inch rolled-rim cans. The
axle for these wheels passes directly through holes in the sides of
the frame.
A piece of galvanized wire 1¼ inches in length is used for driving
pins for the connecting rods on each driving wheel. Each piece of
wire is placed through two holes in the driving wheel, these holes
being directly opposite each other and exactly ½ inch from the
center of each wheel. As these driving pins pass entirely through the
wheel they should be soldered to each side of it in order to give
added strength, as they would break away from the wheels very
easily if they did not pass entirely through the wheel and were not
supported by each side of it.
Cylinders and Connecting Rods.—These cylinders are rolled up
from flat pieces of tin each 2¼ by 3¼ inches. The tin is folded over
on the two shortest sides of each piece before it is formed into a
cylindrical shape, the folded sides of the tin forming each end of the
cylinders.
The connecting rods are made of two strips of tin, each ¾ by 6¼
inches. Both sides of the strip are folded in, making a triple thickness
of tin and a connecting rod about ⁵⁄₁₆ inch wide and 6¼ inches
long.
A disk of tin is soldered to one end of each connecting rod. These
disks should be somewhat smaller than the diameter of the cylinders
so that they may slide easily back and forth inside the cylinders.
The connecting rods have to be bent at the two angles shown in
Fig. 89 so that each rod may be in line with the cylinder and with the
driving wheel.
The Smokestack, Steam Dome and Whistle, Sand Box and
Headlight.—The smokestack is rolled up from a piece of tin 2¾ by
2⅞ inches. This piece of tin is cut from the side of a can so as to
leave the rolled rim at the top for the rim of the stack.
The steam dome is made of the top part of a tooth powder can
with the distributer top left on. This top is left open to form a
whistle. That part of the tooth powder can which rests against the
boiler must be fitted very carefully so as to conform to the curve of
the boiler.
The sand box may be made from a bottle cap and the headlight
may be made from another bottle cap as shown in the drawing.
Cars.—A coal tender for the locomotive may be made from a
small square box mounted on a frame or platform similar to the
locomotive, only smaller. The car wheels may be made from the
small evaporated milk cans or from any small cans obtainable.
A freight car may be made from a long square box in a manner
similar to the coal tender. Passenger cars may be made from long
rectangular cans and the windows and doors may be cut or painted
on the sides or ends. Be sure to place folded strips of tin over any
raw edges left when cutting out windows and doors.
A Passenger Car and Some Others.—A passenger car may be
made from an olive or cooking oil can; that is, about half of one of
the larger cans cut lengthwise. Select a can so that when it is cut
lengthwise to dimension it will be in proportion to the locomotive
which is to be used with it. No dimensions are given in the drawings
as these cans vary in size, but it is not difficult to find a suitable
rectangular can for a passenger car.
When the can is cut open, draw two parallel lines along the sides
for window openings. Do not try to cut each window separately, but
cut one long opening for all the windows, bind the cut edges with
folded strips and then solder folded pieces across the window
openings at intervals for divisions between the windows.
Cut a door in each end of the car and bind the edges with folded
tin. The projecting hoods over the door at each end of the car roof
may be made of part of the sides and bottom of a square can or
from that part of the olive or cooking oil can that is cut away in
making the body of the car.
Fig. 90.

A flat piece of tin may be used for the bottom of the car, this piece
being formed in exactly the same way that the frame of the auto
truck is formed. It is made long enough to allow for a platform at
each end of the car, and the car body is soldered securely to it.
Car wheels may be made from very small cans as any other tin
can wheels are made. Two bottle caps may be soldered together for
a wheel or several flat disks of tin may be cut and soldered together
at the edges to form a wheel. The tin washers used with roofing
nails make an excellent wheel when two are soldered together, back
to back. Never try to use a single can lid, bottle cap or tin disk for a
wheel that is to bear any weight. Any of these are too weak to stand
up alone. The wheels are mounted in the manner shown in the
drawings of the passenger car.
Other cars may be made from cans as shown in Fig. 90, the
construction being so simple as to need no further description.
These cars may be made as simple or as elaborate as the skill of the
maker permits.
CHAPTER XVIII
Simple Mechanical Toys
WATER WHEELS AND SANDMILLS—A SIMPLE
STEAM TURBINE AND BOILER—A
WINDMILL AND TOWER—AEROPLANE
WEATHERVANE

Water wheels and sandmills may be made from bottle caps and
can lids. Two push-in or friction-top can lids are soldered together to
form a flanged wheel and bottle caps are soldered between the
flanges, at equal intervals, for the buckets. The general construction
is shown in Fig. 91. A nozzle may be formed from a piece of tin and
soldered to the standard so that a hose may be connected with it
and to faucet, or, the water wheel may be set in a sink under a
faucet or placed in a stream of running water.
A funnel or sand hopper may be made of tin and soldered to a
standard which holds the bucket wheel. Fine dry sand placed in the
hopper will run through the hole in the bottom and cause the bucket
wheel to revolve.
A Simple Steam Turbine and Boiler.—A very simple and
amusing steam turbine that runs with steam generated in a tin-can
boiler may be made from tin cans. Select a well-soldered can with a
tight-fitting lid, such as a molasses or syrup can with a friction-top
lid. The lid will have to be soldered in place to make it steam tight.
Fig. 91.

Punch a hole about ¼ inch in diameter near one side of the lid for
a filler hole. See that this hole is perfectly round so that a cork may
be fitted in to make it steam tight.
The vane wheel should be about 3 inches in diameter and very
carefully made. See that the axle is soldered exactly in the center of
the wheel. The vanes should be small and numerous and each one
exactly the same size. The method of construction is shown on page
183 (full page drawing). A 3-inch circle is carefully laid out on a flat
piece of tin and then another circle is laid off inside the first one
about ¾ inch in. The outer circle is then divided up into 36 equal
parts. Draw straight lines from each dividing dot at the edge to the
center of the wheel. Bore a small hole exactly where each line
crosses the inner circle. Cut down each dividing line to each hole.
Use the pliers to turn each vane at right angles to the face of the
wheel.
The steam nozzle should be very small. A triangular piece of tin
may be formed around a fine wire nail or pin. The opening in the
nozzle should be about ⅟₃₂ inch in diameter. The nozzle should be
well soldered together and then soldered to the boiler, over a hole of
a suitable size to allow the steam to flow from the boiler into the
nozzle. Be sure not to solder up the tube so that the steam may not
escape. A piece of broom straw may be placed in the nozzle when
soldering it together, and it may be left in when the nozzle is
soldered to the boiler. The straw should extend into the boiler and
may be withdrawn when the soldering operations are completed. Do
not use wire inside the nozzle to prevent it filling with solder as the
solder will stick to it and prevent its being withdrawn.
Use care in placing the nozzle in position under the vane wheel so
that the steam will strike the vanes squarely when it escapes. Set
the end of the nozzle as close to the vanes as possible, but so that it
does not strike the vanes when the wheel revolves.
These turbines run at very high speed when carefully made. Do
not use too much heat under the boiler, as too great pressure may
explode it with disastrous results. If the boiler is set over a gas
flame, take care not to allow the flame to flare out around the boiler
and creep up the sides, as it may then melt off the top of the boiler
even when there is considerable water in it. A moderate flame will
cause enough pressure to be generated in the boiler to make the
vane wheel revolve rapidly. If care is used in fitting the cork in the
filler hole, it may be made steam tight by pushing it into the filler
hole with a light pressure so that if too much pressure is generated
in the boiler the cork will blow out.
A pinion from a small clock works may be soldered to the vane
wheel shaft and meshed in with a large gear which is set on a shaft
soldered to the supporting upright at one side of the wheel. A small
pulley may be made of wood or metal and fastened to the large
gear. This arrangement of gears will give a reduced speed and a
string belt may be run from the pulley to some light running toy
machine. The pinion and gear fastened to the turbine should run
very easily.
An alcohol heating lamp may be made for the turbine boiler by
soldering a wick tube and a vent tube to a shoe paste or salve box.
The wick tube should be made from a strip of tin rolled up into a
cylindrical shape. It should be about ½ inch in diameter and 1½
inches in length when soldered together. The wick tube should
extend about 1 inch above the top of the lamp and it should be
soldered firmly in a hole cut in the top of the lamp to receive it.
A small tube about ¼ inch in diameter and 3 inches long is
soldered together. This tube should be soldered over a hole near the
side of the lamp at the top and soldered on at an angle as shown in
Fig. 91. It serves as a vent, allowing the alcohol gas generated
within the top of the lamp to escape and it also serves as a handle.
An alcohol lamp fitted with a vent tube of this description will not
boil over and catch fire as so many of the small alcohol lamps
provided with toy steam engines are sure to do. Vent tubes soldered
to these lamps in such a manner as to conduct the gas away from
the flame will provide against accidents of this sort.
A filler hole should be placed in the top of the lamp as far away
from the wick tube as possible. A common cork may be used as a
stopper. A small funnel may be easily made from some pieces of
scrap tin and used for filling the boiler and the lamp.
A Windmill and Tower.—A windmill and tower that will look
very realistic when completed may be made from tin cans. The vane
wheel is composed of twelve blades set in two can lids. The vanes
are cut from a flat piece of tin, care being taken to make each one
exactly the same size. A large can lid is used for the outer vane
support and the central part of this lid is cut away. Twelve cuts are
made around the edge of the can lid at equal distances and the
vanes soldered in these cuts.
A small can lid is used for the center of the wheel and the ends of
the vanes soldered to it.
The tower is made of strips of folded tin and the tank from a tin
can is shown in Fig. 92.
Aeroplane Weathervane.—A biplane weathervane may be
made from flat strips of tin. Large round or square cans may be
opened out and the tin taken from them used to make the aeroplane
weathervane. When this weathervane is mounted on a suitable spike
on which it may turn about freely in the wind, the propeller will
revolve rapidly when the wind blows.
Fig. 92.

PLATE XVIII
Aeroplane weather vanes made by the author
The construction of the aeroplane is quite simple and the principal
dimensions are given in Fig. 93. The construction is very well shown
in Plate XVIII. If the foregoing problems have been satisfactorily
worked out there will be no difficulty in constructing the aeroplane
from the dimensions given.
The two wings are made from two pieces of tin of the required
size with the edges folded over.
The body of fuselage is made of a long triangular piece of tin
folded up on each side so as to form a sort of long tapering box. A
cover is made for this box and divided into two parts so as to leave a
cockpit opening.
The struts or wing supports are made from narrow strips of tin
that are folded almost together for strength. The small guy wires
had best be made from copper wire of small diameter. If it is difficult
to get small copper wire, it may be possible to get two or three feet
of insulated copper wire used for electrical purposes. Such wire is
employed to wind small magnets used on electric bells. The
insulation easily burns off. Copper wire solders very easily.
Fig. 93.

The rudder and tail planes are made from flat pieces of tin. A
straight piece of wire is used for the propeller shaft. A tube is made
of tin and used as a bearing for the shaft. The propeller shaft should
fit very loosely in the tube. The bearing tube is soldered firmly to the
body of the aeroplane as shown in Fig. 93. When completely
assembled, except for the propeller and its shaft, the propeller is
soldered to one end of the shaft. Care should be taken to mount the
propeller blade in such a way that the shaft is exactly in the center,
Welcome to our website – the perfect destination for book lovers and
knowledge seekers. We believe that every book holds a new world,
offering opportunities for learning, discovery, and personal growth.
That’s why we are dedicated to bringing you a diverse collection of
books, ranging from classic literature and specialized publications to
self-development guides and children's books.

More than just a book-buying platform, we strive to be a bridge


connecting you with timeless cultural and intellectual values. With an
elegant, user-friendly interface and a smart search system, you can
quickly find the books that best suit your interests. Additionally,
our special promotions and home delivery services help you save time
and fully enjoy the joy of reading.

Join us on a journey of knowledge exploration, passion nurturing, and


personal growth every day!

ebookbell.com

You might also like