Book description
Stay on top of the new Java features (up to JDK 21) and find efficient solutions for your programming woes. With over 250 problems and solutions, you'll learn new ways to deal with real-world coding tasks and answers to common interview questions. Purchase of the print or Kindle book includes a free PDF eBook
Key Features
- Solve Java programming challenges and get interview-ready with the power of modern Java 21
- Test your Java skills using language features, algorithms, data structures, and design patterns
- Explore tons of examples, all fully refreshed for this edition, meant to help you accommodate JDK 12 to JDK 21
Book Description
The super-fast evolution of the JDK between versions 12 and 21 has made the learning curve of modern Java steeper, and increased the time needed to learn it. This book will make your learning journey quicker and increase your willingness to try Java’s new features by explaining the correct practices and decisions related to complexity, performance, readability, and more.
Java Coding Problems takes you through Java’s latest features but doesn’t always advocate the use of new solutions — instead, it focuses on revealing the trade-offs involved in deciding what the best solution is for a certain problem.
There are more than two hundred brand new and carefully selected problems in this second edition, chosen to highlight and cover the core everyday challenges of a Java programmer.
Apart from providing a comprehensive compendium of problem solutions based on real-world examples, this book will also give you the confidence to answer questions relating to matching particular streams and methods to various problems.
By the end of this book you will have gained a strong understanding of Java’s new features and have the confidence to develop and choose the right solutions to your problems.
What you will learn
- Adopt the latest JDK 21 features in your applications
- Explore Records, Record Patterns, Record serialization and so on
- Work with Sealed Classes and Interfaces for increasing encapsulation
- Learn how to exploit Context-Specific Deserialization Filters
- Solve problems relating to collections and esoteric data structures
- Learn advanced techniques for extending the Java functional API
- Explore the brand-new Socket API and Simple Web Server
- Tackle modern Garbage Collectors and Dynamic CDS Archives
Who this book is for
If you are a Java developer who wants to level-up by solving real-world problems, then this book is for you. Working knowledge of the Java programming language is required to get the most out of this book
Table of contents
- Preface
-
Text Blocks, Locales, Numbers, and Math
- Problems
- 1. Creating a multiline SQL, JSON, and HTML string
- 2. Exemplifying the usage of text block delimiters
- 3. Working with indentation in text blocks
- 4. Removing incidental white spaces in text blocks
- 5. Using text blocks just for readability
- 6. Escaping quotes and line terminators in text blocks
- 7. Translating escape sequences programmatically
- 8. Formatting text blocks with variables/expressions
- 9. Adding comments in text blocks
- 10. Mixing ordinary string literals with text blocks
- 11. Mixing regular expression with text blocks
- 12. Checking if two text blocks are isomorphic
- 13. Concatenating strings versus StringBuilder
- 14. Converting int to String
- 15. Introducing string templates
- 16. Writing a custom template processor
- 17. Creating a Locale
- 18. Customizing localized date-time formats
- 19. Restoring Always-Strict Floating-Point semantics
- 20. Computing mathematical absolute value for int/long and result overflow
- 21. Computing the quotient of the arguments and result overflow
- 22. Computing the largest/smallest value that is less/greater than or equal to the algebraic quotient
- 23. Getting integral and fractional parts from a double
- 24. Testing if a double number is an integer
- 25. Hooking Java (un)signed integers in a nutshell
- 26. Returning the flooring/ceiling modulus
- 27. Collecting all prime factors of a given number
- 28. Computing the square root of a number using the Babylonian method
- 29. Rounding a float number to specified decimals
- 30. Clamping a value between min and max
- 31. Multiply two integers without using loops, multiplication, bitwise, division, and operators
- 32. Using TAU
- 33. Selecting a pseudo-random number generator
- 34. Filling a long array with pseudo-random numbers
- 35. Creating a stream of pseudo-random generators
- 36. Getting a legacy pseudo-random generator from new ones of JDK 17
- 37. Using pseudo-random generators in a thread-safe fashion (multithreaded environments)
- Summary
-
Objects, Immutability, Switch Expressions, and Pattern Matching
- Problems
- 38. Explain and exemplifying UTF-8, UTF-16, and UTF-32
- 39. Checking a sub-range in the range from 0 to length
- 40. Returning an identity string
- 41. Hooking unnamed classes and instance main methods
- 42. Adding code snippets in Java API documentation
- 43. Invoking default methods from Proxy instances
- 44. Converting between bytes and hex-encoded strings
- 45. Exemplify the initialization-on-demand holder design pattern
- 46. Adding nested classes in anonymous classes
- 47. Exemplify erasure vs. overloading
- 48. Xlinting default constructors
- 49. Working with the receiver parameter
- 50. Implementing an immutable stack
- 51. Revealing a common mistake with Strings
-
52. Using the enhanced NullPointerException
- WARNING 1! NPE when calling an instance method via a null object
- WARNING 2! NPE when accessing (or modifying) the field of a null object
- WARNING 3! NPE when null is passed in the method argument
- WARNING 4! NPE when accessing the index value of a null array/collection
- WARNING 5! NPE when accessing a field via a getter
- 53. Using yield in switch expressions
- 54. Tackling the case null clause in switch
- 55. Taking on the hard way to discover equals()
- 56. Hooking instanceof in a nutshell
- 57. Introducing pattern matching
- 58. Introducing type pattern matching for instanceof
- 59. Handling the scope of a binding variable in type patterns for instanceof
- 60. Rewriting equals() via type patterns for instanceof
- 61. Tackling type patterns for instanceof and generics
- 62. Tackling type patterns for instanceof and streams
- 63. Introducing type pattern matching for switch
- 64. Adding guarded pattern labels in switch
- 65. Dealing with pattern label dominance in switch
- 66. Dealing with completeness (type coverage) in pattern labels for switch
- 67. Understanding the unconditional patterns and nulls in switch expressions
- Summary
-
Working with Date and Time
- Problems
- 68. Defining a day period
- 69. Converting between Date and YearMonth
- 70. Converting between int and YearMonth
- 71. Converting week/year to Date
- 72. Checking for a leap year
- 73. Calculating the quarter of a given date
- 74. Getting the first and last day of a quarter
- 75. Extracting the months from a given quarter
- 76. Computing pregnancy due date
- 77. Implementing a stopwatch
- 78. Extracting the count of milliseconds since midnight
- 79. Splitting a date-time range into equal intervals
- 80. Explaining the difference between Clock.systemUTC() and Clock.systemDefaultZone()
- 81. Displaying the names of the days of the week
- 82. Getting the first and last day of the year
- 83. Getting the first and last day of the week
- 84. Calculating the middle of the month
- 85. Getting the number of quarters between two dates
- 86. Converting Calendar to LocalDateTime
- 87. Getting the number of weeks between two dates
- Summary
-
Records and Record Patterns
- Problems
- 88. Declaring a Java record
- 89. Introducing the canonical and compact constructors for records
- 90. Adding more artifacts in a record
- 91. Iterating what we cannot have in a record
- 92. Defining multiple constructors in a record
- 93. Implementing interfaces in records
- 94. Understanding record serialization
- 95. Invoking the canonical constructor via reflection
- 96. Using records in streams
- 97. Introducing record patterns for instanceof
- 98. Introducing record patterns for switch
- 99. Tackling guarded record patterns
- 100. Using generic records in record patterns
- 101. Handling nulls in nested record patterns
- 102. Simplifying expressions via record patterns
- 103. Hooking unnamed patterns and variables
- 104. Tackling records in Spring Boot
- 105. Tackling records in JPA
- 106. Tackling records in jOOQ
- Summary
-
Arrays, Collections, and Data Structures
- Problems
- 107. Introducing parallel computations with arrays
- 108. Covering the Vector API’s structure and terminology
- 109. Summing two arrays via the Vector API
- 110. Summing two arrays unrolled via the Vector API
- 111. Benchmarking the Vector API
- 112. Applying the Vector API to compute FMA
- 113. Multiplying matrices via the Vector API
- 114. Hooking the image negative filter with the Vector API
- 115. Dissecting factory methods for collections
- 116. Getting a list from a stream
- 117. Handling map capacity
- 118. Tackling Sequenced Collections
- 119. Introducing the Rope data structure
- 120. Introducing the Skip List data structure
- 121. Introducing the K-D Tree data structure
- 122. Introducing the Zipper data structure
- 123. Introducing the Binomial Heap data structure
- 124. Introducing the Fibonacci Heap data structure
- 125. Introducing the Pairing Heap data structure
- 126. Introducing the Huffman Coding data structure
- 127. Introducing the Splay Tree data structure
- 128. Introducing the Interval Tree data structure
- 129. Introducing the Unrolled Linked List data structure
- 130. Implementing join algorithms
- Summary
-
Java I/O: Context-Specific Deserialization Filters
- Problems
- 131. Serializing objects to byte arrays
- 132. Serializing objects to strings
- 133. Serializing objects to XML
- 134. Introducing JDK 9 deserialization filters
- 135. Implementing a custom pattern-based ObjectInputFilter
- 136. Implementing a custom class ObjectInputFilter
- 137. Implementing a custom method ObjectInputFilter
- 138. Implementing a custom lambda ObjectInputFilter
- 139. Avoiding StackOverflowError at deserialization
- 140. Avoiding DoS attacks at deserialization
- 141. Introducing JDK 17 easy filter creation
- 142. Tackling context-specific deserialization filters
- 143. Monitoring deserialization via JFR
- Summary
-
Foreign (Function) Memory API
- Problems
- 144. Introducing Java Native Interface (JNI)
- 145. Introducing Java Native Access (JNA)
- 146. Introducing Java Native Runtime (JNR)
- 147. Motivating and introducing Project Panama
- 148. Introducing Panama’s architecture and terminology
- 149. Introducing Arena and MemorySegment
- 150. Allocating arrays into memory segments
- 151. Understanding addresses (pointers)
- 152. Introducing the sequence layout
- 153. Shaping C-like structs into memory segments
- 154. Shaping C-like unions into memory segments
- 155. Introducing PaddingLayout
- 156. Copying and slicing memory segments
- 157. Tackling the slicing allocator
- 158. Introducing the slice handle
- 159. Introducing layout flattening
- 160. Introducing layout reshaping
- 161. Introducing the layout spreader
- 162. Introducing the memory segment view VarHandle
- 163. Streaming memory segments
- 164. Tackling mapped memory segments
- 165. Introducing the Foreign Linker API
- 166. Calling the sumTwoInt() foreign function
- 167. Calling the modf() foreign function
- 168. Calling the strcat() foreign function
- 169. Calling the bsearch() foreign function
- 170. Introducing Jextract
- 171. Generating native binding for modf()
- Summary
-
Sealed and Hidden Classes
- Problems
- 172. Creating an electrical panel (hierarchy of classes)
- 173. Closing the electrical panel before JDK 17
- 174. Introducing JDK 17 sealed classes
- 175. Introducing the permits clause
- 176. Closing the electrical panel after JDK 17
- 177. Combining sealed classes and records
- 178. Hooking sealed classes and instanceof
- 179. Hooking sealed classes in switch
- 180. Reinterpreting the Visitor pattern via sealed classes and type pattern matching for switch
- 181. Getting info about sealed classes (using reflection)
- 182. Listing the top three benefits of sealed classes
- 183. Briefly introducing hidden classes
- 184. Creating a hidden class
- Summary
-
Functional Style Programming – Extending APIs
- Problems
- 185. Working with mapMulti()
- 186. Streaming custom code to map
- 187. Exemplifying a method reference vs. a lamda
- 188. Hooking lambda laziness via Supplier/Consumer
- 189. Refactoring code to add lambda laziness
- 190. Writing a Function<String, T> for parsing data
- 191. Composing predicates in a Stream’s filters
- 192. Filtering nested collections with Streams
- 193. Using BiPredicate
- 194. Building a dynamic predicate for a custom model
- 195. Building a dynamic predicate from a custom map of conditions
- 196. Logging in predicates
- 197. Extending Stream with containsAll() and containsAny()
- 198. Extending Stream with removeAll() and retainAll()
- 199. Introducing stream comparators
- 200. Sorting a map
- 201. Filtering a map
- 202. Creating a custom collector via Collector.of()
- 203. Throwing checked exceptions from lambdas
- 204. Implementing distinctBy() for the Stream API
- 205. Writing a custom collector that takes/skips a given number of elements
- 206. Implementing a Function that takes five (or any other arbitrary number of) arguments
- 207. Implementing a Consumer that takes five (or any other arbitrary number of) arguments
- 208. Partially applying a Function
- Summary
-
Concurrency – Virtual Threads and Structured Concurrency
- Problems
- 209. Explaining concurrency vs. parallelism
- 210. Introducing structured concurrency
- 211. Introducing virtual threads
- 212. Using the ExecutorService for virtual threads
- 213. Explaining how virtual threads work
- 214. Hooking virtual threads and sync code
- 215. Exemplifying thread context switching
- 216. Introducing the ExecutorService invoke all/any for virtual threads – part 1
- 217. Introducing the ExecutorService invoke all/any for virtual threads – part 2
- 218. Hooking task state
- 219. Combining newVirtualThreadPerTaskExecutor() and streams
- 220. Introducing a scope object (StructuredTaskScope)
- 221. Introducing ShutdownOnSuccess
- 222. Introducing ShutdownOnFailure
- 223. Combining StructuredTaskScope and streams
- 224. Observing and monitoring virtual threads
- Summary
-
Concurrency ‒ Virtual Threads and Structured Concurrency: Diving Deeper
- Problems
- 225. Tackling continuations
- 226. Tracing virtual thread states and transitions
- 227. Extending StructuredTaskScope
- 228. Assembling StructuredTaskScope
- 229. Assembling StructuredTaskScope instances with timeout
- 230. Hooking ThreadLocal and virtual threads
- 231. Hooking ScopedValue and virtual threads
- 232. Using ScopedValue and executor services
- 233. Chaining and rebinding scoped values
- 234. Using ScopedValue and StructuredTaskScope
- 235. Using Semaphore instead of Executor
- 236. Avoiding pinning via locking
- 237. Solving the producer-consumer problem via virtual threads
- 238. Solving the producer-consumer problem via virtual threads (fixed via Semaphore)
- 239. Solving the producer-consumer problem via virtual threads (increase/decrease consumers)
- 240. Implementing an HTTP web server on top of virtual threads
- 241. Hooking CompletableFuture and virtual threads
- 242. Signaling virtual threads via wait() and notify()
- Summary
-
Garbage Collectors and Dynamic CDS Archives
- Problems
- 243. Hooking the garbage collector goal
- 244. Handling the garbage collector stages
- 245. Covering some garbage collector terminology
- 246. Tracing the generational GC process
- 247. Choosing the correct garbage collector
- 248. Categorizing garbage collectors
- 249. Introducing G1
- 250. Tackling G1 throughput improvements
- 251. Tackling G1 latency improvements
- 252. Tackling G1 footprint improvements
- 253. Introducing ZGC
- 254. Monitoring garbage collectors
- 255. Logging garbage collectors
- 256. Tuning garbage collectors
- 257. Introducing Application Class Data Sharing (AppCDS, or Java’s Startup Booster)
- Summary
-
Socket API and Simple Web Server
- Problems
- 258. Introducing socket basics
- 259. Introducing TCP server/client applications
- 260. Introducing the Java Socket API
- 261. Writing a blocking TCP server/client application
- 262. Writing a non-blocking TCP server/client application
- 263. Writing UDP server/client applications
- 264. Introducing multicasting
- 265. Exploring network interfaces
- 266. Writing a UDP multicast server/client application
- 267. Adding KEM to a TCP server/client application
- 268. Reimplementing the legacy Socket API
- 269. Quick overview of SWS
- 270. Exploring the SWS command-line tool
- 271. Introducing the com.sun.net.httpserver API
- 272. Adapting request/exchange
- 273. Complementing a conditional HttpHandler with another handler
- 274. Implementing SWS for an in-memory file system
- 275. Implementing SWS for a zip file system
- 276. Implementing SWS for a Java runtime directory
- Summary
- Other Books You May Enjoy
- Index
Product information
- Title: Java Coding Problems - Second Edition
- Author(s):
- Release date: March 2024
- Publisher(s): Packt Publishing
- ISBN: 9781837633944
You might also like
book
Java Coding Problems
Develop your coding skills by exploring Java concepts and techniques such as Strings, Objects and Types, …
book
The Well-Grounded Java Developer, Second Edition
Understanding Java from the JVM up gives you a solid foundation to grow your expertise and …
book
Java Performance, 2nd Edition
Coding and testing are generally considered separate areas of expertise. In this practical book, Java expert …
book
Java in a Nutshell, 8th Edition
This updated edition of the Nutshell guide not only helps experienced Java programmers get the most …