
- •Contents at a Glance
- •Contents
- •About the Authors
- •About the Technical Reviewer
- •Acknowledgments
- •Introduction
- •Oracle Java Certifications: Overview
- •FAQ 1. What are the different levels of Oracle Java certification exams?
- •FAQ 4. Is OCPJP 7 prerequisite for other Oracle certification exams?
- •FAQ 5. Should I take the OCPJP 7 or OCPJP 6 exam?
- •The OCPJP 7 Exam
- •FAQ 7. How many questions are there in the OCPJP 7 exam?
- •FAQ 8. What is the duration of the OCPJP 7 exam?
- •FAQ 9. What is the cost of the OCPJP 7 exam?
- •FAQ 10. What are the passing scores for the OCPJP 7 exam?
- •FAQ 11. What kinds of questions are asked in the OCPJP 7 exam?
- •FAQ 12. What does the OCPJP 7 exam test for?
- •FAQ 13. I’ve been a Java programmer for last five years. Do I have to prepare for the OCPJP 7 exam?
- •FAQ 14. How do I prepare for the OCPJP 7 exam?
- •FAQ 15. How do I know when I’m ready to take the OCPJP 7 exam?
- •Taking the OCPJP 7 Exam
- •FAQ 16. What are my options to register for the exam?
- •FAQ 17. How do I register for the exam, schedule a day and time for taking the exam, and appear for the exam?
- •The OCPJP 7 Exam: Pretest
- •Answers with Explanations
- •Post-Pretest Evaluation
- •Essentials of OOP
- •FunPaint Application: An Example
- •Foundations of OOP
- •Abstraction
- •Encapsulation
- •Inheritance
- •Polymorphism
- •Class Fundamentals
- •Object Creation
- •Constructors
- •Access Modifiers
- •Public Access Modifier
- •Private Access Modifier
- •Protected and Default Access Modifier
- •Overloading
- •Method Overloading
- •Constructor Overloading
- •Overload resolution
- •Points to Remember
- •Inheritance
- •Runtime Polymorphism
- •An Example
- •Overriding Issues
- •Overriding: Deeper Dive
- •Invoking Superclass Methods
- •Type Conversions
- •Upcasts and Downcasts
- •Casting Between Inconvertible Types
- •Using “instanceof” for Safe Downcasts
- •Java Packages
- •Working with Packages
- •Static Import
- •Summary
- •Abstract Classes
- •Points to Remember
- •Using the “final” Keyword
- •Final Classes
- •Final Methods and Variables
- •Points to Remember
- •Using the “static” Keyword
- •Static Block
- •Points to Remember
- •Flavors of Nested Classes
- •Static Nested Classes (or Interfaces)
- •Points to Remember
- •Inner Classes
- •Points to Remember
- •Local Inner Classes
- •Points to Remember
- •Anonymous Inner Classes
- •Points to Remember
- •Enum Data Types
- •Points to Remember
- •Summary
- •Interfaces
- •Declaring and Using Interfaces
- •Points to Remember
- •Abstract Classes vs. Interfaces
- •Choosing Between an Abstract Class and an Interface
- •Object Composition
- •Composition vs. Inheritance
- •Points to Remember
- •Design Patterns
- •The Singleton Design Pattern
- •Ensuring That Your Singleton Is Indeed a Singleton
- •The Factory Design Pattern
- •Differences Between Factory and Abstract Factory Design Patterns
- •The Data Access Object (DAO) Design Pattern
- •Points to Remember
- •Summary
- •Generics
- •Using Object Type and Type Safety
- •Using the Object Class vs. Generics
- •Container Implementation Using the Object Class
- •Container Implementation Using Generics
- •Creating Generic Classes
- •Diamond Syntax
- •Interoperability of Raw Types and Generic Types
- •Generic Methods
- •Generics and Subtyping
- •Wildcard Parameters
- •Limitations of Wildcards
- •Bounded Wildcards
- •Wildcards in the Collections Class
- •Points to Remember
- •The Collections Framework
- •Why Reusable Classes?
- •Basic Components of the Collections Framework
- •Abstract Classes and Interfaces
- •Concrete Classes
- •List Classes
- •ArrayList Class
- •The ListIterator Interface
- •The LinkedList Class
- •The Set Interface
- •The HashSet Class
- •The TreeSet Class
- •The Map Interface
- •The HashMap Class
- •Overriding the hashCode() Method
- •The NavigableMap Interface
- •The Queue Interface
- •The Deque Interface
- •Comparable and Comparator Interfaces
- •Algorithms (Collections Class)
- •The Arrays Class
- •Methods in the Arrays Class
- •Array as a List
- •Points to Remember
- •Summary
- •Generics
- •Collections Framework
- •Processing Strings
- •String Searching
- •The IndexOf() Method
- •The regionMatches() Method
- •String Parsing
- •String Conversions
- •The Split() Method
- •Regular Expressions
- •Understanding regex Symbols
- •Regex Support in Java
- •Searching and Parsing with regex
- •Replacing Strings with regex
- •String Formatting
- •Format Specifiers
- •Points to Remember
- •Summary
- •Reading and Writing from Console
- •Understanding the Console Class
- •Formatted I/O with the Console Class
- •Special Character Handling in the Console Class
- •Using Streams to Read and Write Files
- •Character Streams and Byte Streams
- •Character Streams
- •Reading Text Files
- •Reading and Writing Text Files
- •“Tokenizing” Text
- •Byte Streams
- •Reading a Byte Stream
- •Data Streams
- •Writing to and Reading from Object Streams: Serialization
- •Serialization: Some More Details
- •Points to Remember
- •Summary
- •A Quick History of I/O APIs
- •Using the Path Interface
- •Getting Path Information
- •Comparing Two Paths
- •Using the Files Class
- •Checking File Properties and Metadata
- •Copying a File
- •Moving a File
- •Deleting a File
- •Walking a File Tree
- •Revisiting File Copy
- •Finding a File
- •Watching a Directory for Changes
- •Points to Remember
- •Summary
- •Introduction to JDBC
- •The Architecture of JDBC
- •Two-Tier and Three-Tier JDBC Architecture
- •Types of JDBC Drivers
- •Setting Up the Database
- •Connecting to a Database Using a JDBC Driver
- •The Connection Interface
- •Connecting to the Database
- •Statement
- •ResultSet
- •Querying the Database
- •Updating the Database
- •Getting the Database Metadata
- •Points to Remember
- •Querying and Updating the Database
- •Performing Transactions
- •Rolling Back Database Operations
- •The RowSet Interface
- •Points to Remember
- •Summary
- •Define the Layout of the JDBC API
- •Connect to a Database by Using a JDBC driver
- •Update and Query a Database
- •Customize the Transaction Behavior of JDBC and Commit Transactions
- •Use the JDBC 4.1 RowSetProvider, RowSetFactory, and RowSet Interfaces
- •Introduction to Exception Handling
- •Throwing Exceptions
- •Unhandled Exceptions
- •Try and Catch Statements
- •Programmatically Accessing the Stack Trace
- •Multiple Catch Blocks
- •Multi-Catch Blocks
- •General Catch Handlers
- •Finally Blocks
- •Points to Remember
- •Try-with-Resources
- •Closing Multiple Resources
- •Points to Remember
- •Exception Types
- •The Exception Class
- •The RuntimeException Class
- •The Error Class
- •The Throws Clause
- •Method Overriding and the Throws Clause
- •Points to Remember
- •Custom Exceptions
- •Assertions
- •Assert Statement
- •How Not to Use Asserts
- •Summary
- •Introduction
- •Locales
- •The Locale Class
- •Getting Locale Details
- •Resource Bundles
- •Using PropertyResourceBundle
- •Using ListResourceBundle
- •Loading a Resource Bundle
- •Naming Convention for Resource Bundles
- •Formatting for Local Culture
- •The NumberFormat Class
- •The Currency Class
- •The DateFormat Class
- •The SimpleDateFormat Class
- •Points to Remember
- •Summary
- •Introduction to Concurrent Programming
- •Important Threading-Related Methods
- •Creating Threads
- •Extending the Thread Class
- •Implementing the Runnable Interface
- •The Start( ) and Run( ) Methods
- •Thread Name, Priority, and Group
- •Using the Thread.sleep() Method
- •Using Thread’s Join Method
- •Asynchronous Execution
- •The States of a Thread
- •Two States in “Runnable” State
- •Concurrent Access Problems
- •Data Races
- •Thread Synchronization
- •Synchronized Blocks
- •Synchronized Methods
- •Synchronized Blocks vs. Synchronized Methods
- •Deadlocks
- •Other Threading Problems
- •Livelocks
- •Lock Starvation
- •The Wait/Notify Mechanism
- •Let’s Solve a Problem
- •More Thread States
- •timed_waiting and blocked States
- •waiting State
- •Using Thread.State enum
- •Understanding IllegalThreadStateException
- •Summary
- •Using java.util.concurrent Collections
- •Semaphore
- •CountDownLatch
- •Exchanger
- •CyclicBarrier
- •Phaser
- •Concurrent Collections
- •Apply Atomic Variables and Locks
- •Atomic Variables
- •Locks
- •Conditions
- •Multiple Conditions on a Lock
- •Use Executors and ThreadPools
- •Executor
- •Callable, Executors, ExecutorService, ThreadPool, and Future
- •ThreadFactory
- •The ThreadLocalRandom Class
- •TimeUnit Enumeration
- •Use the Parallel Fork/Join Framework
- •Useful Classes of the Fork/Join Framework
- •Using the Fork/Join Framework
- •Points to Remember
- •Summary
- •Using java.util.concurrent Collections
- •Applying Atomic Variables and Locks
- •Using Executors and ThreadPools
- •Using the Parallel Fork/Join Framework
- •Chapter 3: Java Class Design
- •Chapter 4: Advanced Class Design
- •Chapter 5: Object-Oriented Design Principles
- •Chapter 6: Generics and Collections
- •Chapter 7: String Processing
- •Chapter 8: Java I/O Fundamentals
- •Chapter 9: Java File I/O (NIO.2)
- •Chapter 10: Building Database Applications with JDBC
- •Chapter 11: Exceptions and Assertions
- •Chapter 12: Localization
- •Chapter 13: Threads
- •Chapter 14: Concurrency
- •OCPJP7 Exam (1Z0-804 a.k.a. Java SE 7 Programmer II) Topics
- •OCPJP 7 Exam (1Z0-805, a.k.a. Upgrade to Java SE 7 Programmer) Topics
- •Answers and Explanations
- •Answer Sheet
- •Answers and Explanations
- •Index

Chapter 7 ■ String Processing
Table 7-4. (continued)
Symbol Description
\W |
Matches non-word characters. |
\s |
Matches whitespaces (equivalent to [\t\r\f\n]). |
\S |
Matches non-whitespaces. |
\b |
Matches word boundary when outside bracket. Matches backslash when inside bracket. |
\B |
Matches non-word boundary. |
\A |
Matches beginning of string. |
\Z |
Matches end of string. |
|
|
Okay, so far so good. But what if you want to specify a regex when the match involves an occurrence count of characters? Well, for such situations you can use quantifier symbols, provided in Table 7-5.
Table 7-5. Commonly Used Quantifier Symbols
|
|
Symbol |
Description |
expr? |
Matches 0 or 1 occurrence of expr (equivalent to expr{0,1}). |
expr* |
Matches 0 or more occurrences of expr (equivalent to expr{0,}). |
expr+ |
Matches 1 or more occurrences of expr (equivalent to expr{1,}). |
expr{x} |
Matches x occurrences of expr. |
expr{x, y} |
Matches between x and y occurrences of expr. |
expr{x,} |
Matches x or more occurrences of expr. |
|
|
Regex Support in Java
Java 1.4 SDK introduced regex support in Java. The package java.util.regex supports regex. It consists of two important classes, Pattern and Matcher. Pattern represents a regex in a compiled representation, and Matcher interprets a regex and matches the corresponding substring in a given string.
At this point, you may ask why is regex supported by dedicated classes such as Matcher and Pattern when other methods such as split() in the String class already support regex? The single word answer for this question is: performance. The Pattern and Matcher classes are optimized for performance while methods like split() in String are not.
Use the Pattern and Matcher classes whenever you are performing search or replace on strings heavily; they are more efficient than split() in String or other methods.
Now, let’s see how you can use the Pattern and Matcher classes. You first need to call a static method compile() in the Pattern class to get an instance of a pattern. The first argument of this method is a regex. Then, you need to call another static method called matcher() from the Pattern class to get an instance of the Matcher class. The matcher() method returns a Matcher object. This object is then used to execute the required operation on the input string.
212

Chapter 7 ■ String Processing
Let’s look at how to use the Pattern and Matcher classes. Let’s assume that you have a string consisting of personal details (such as name, address, phone number) of a set of people. You will use the following string for the examples covered in rest of this section:
String str = "Danny Doo, Flat no 502, Big Apartment, Wide Road, Near Huge Milestone, Hugo-city 56010, Ph: 9876543210, Email: danny@myworld.com. Maggi Myer, Post bag no 52, Big bank post office, Big bank city 56000, ph: 9876501234, Email: maggi07@myuniverse.com.";
You need to specify regex using the backslash (\); do not use the forward slash (/) instead. The compiler will not give any error if you use the forward slash; however, you won’t get the desired output.
Searching and Parsing with regex
Let’s start with a simple example. You need to write code to print all words of the string str. How can you do this? Well, do you remember metacharacter "\w", which matches with all symbols forming a word? You are going to use "\w" along with the quantifier "+" to make "\w+", which means you want to search all words of length one or more; see Listing 7-7.
Listing 7-7. Regex1.java
import java.util.regex.Matcher; import java.util.regex.Pattern;
public class Regex1 {
public static void main(String[] args) {
String str = "Danny Doo, Flat no 502, Big Apartment, Wide Road, Near Huge Milestone, Hugo-city 56010, Ph: 9876543210, Email: danny@myworld.com. Maggi Myer, Post bag no 52, Big bank post office, Big bank city 56000, ph: 9876501234, Email: maggi07@myuniverse.com.";
Pattern pattern = Pattern.compile("\\w+"); Matcher matcher = pattern.matcher(str); while(matcher.find()) {
System.out.println(matcher.group());
}
}
}
It prints the following:
Danny Doo Flat no 502
...
maggi07 myuniverse com
213

Chapter 7 ■ String Processing
(Note that we have truncated the results with . . . to save space.) However, you can see that the regular expression searched all words consisting at least one character. What happened here was that you invoked the compile() method along with a regex of the Pattern class to get an instance of Pattern. After that, you got an instance of the Matcher class by calling the matcher() method on pattern instance. And finally you got the result using the group() and find() methods of the Matcher class. The method find() returns true if there exists any search result. The group() method returns a search result occurrence as a string.
Note that we used two backslashes in the regex (“\\w+”) specified in Listing 7-7 because backslash is a escape character in regex. However, backslash is also a escape character in Java strings, which means literal “\\” is interpreted as a single backslash. This translates to an interesting outcome:
we write “\\” as a single backslash in a regex, which will be written as “\\\\” in a Java program if we want to specify a single backslash.
In the same way, you can search all the numbers using the "\d+" regex. Now, let’s say you want to search and print all ZIP codes (postal code) appeared in the string. Assume that the ZIP code length is always 5. Can you achieve this using regex? Will the program in Listing 7-8 work?
Listing 7-8. Regex2.java
import java.util.regex.Matcher; import java.util.regex.Pattern;
// This program demonstrates how we can search numbers of a specified length public class Regex2 {
public static void main(String[] args) {
String str = "Danny Doo, Flat no 502, Big Apartment, Wide Road, Near Huge Milestone, Hugo-city 56010, Ph: 9876543210, Email: danny@myworld.com. Maggi Myer, Post bag no 52, Big bank post office, Big bank city 56000, ph: 9876501234, Email: maggi07@myuniverse.com.";
Pattern pattern = Pattern.compile("\\d{5}"); Matcher matcher = pattern.matcher(str); while(matcher.find()) {
System.out.println(matcher.group());
}
}
}
You used "\d{5}" as the regex string. Let’s see what this program prints:
56010
98765
43210
56000
98765
01234
Oops! It has printed two ZIP codes but also printed three partial phone numbers, which was unexpected. Hmm, to get only the ZIP codes, you must specify the regex more properly. Try again with Listing 7-9.
214
Chapter 7 ■ String Processing
Listing 7-9. Regex3.java
import java.util.regex.Matcher; import java.util.regex.Pattern;
// This program demonstrates how we can search numbers of a specified length public class Regex3 {
public static void main(String[] args) {
String str = "Danny Doo, Flat no 502, Big Apartment, Wide Road, Near Huge Milestone, Hugo-city 56010, Ph: 9876543210, Email: danny@myworld.com. Maggi Myer, Post bag no 52, Big bank post office, Big bank city 56000, ph: 9876501234, Email: maggi07@myuniverse.com.";
Pattern pattern = Pattern.compile("\\D\\d{5}\\D"); Matcher matcher = pattern.matcher(str); while(matcher.find()) {
System.out.println(matcher.group());
}
}
}
It prints the following:
56010,
56000,
This time you used "\D\d{5}\D" and it worked well. What you essentially did was specify that a non-digit character is preceded and followed by a six-digit number. Easy, right! Well, there is a problem in this solution.
The program is printing one whitespace just before the six-digit number and a comma just after the six-digit number (both matched by "\D"). Can you get rid of these unwanted characters? Yes, there is an elegant solution to this: you can use "\b" (used to detect word boundaries) here. See if this works by trying the code in Listing 7-10.
Listing 7-10. RegexDemo.java
import java.util.regex.Matcher; import java.util.regex.Pattern;
// This program demonstrates how we can search numbers of a specified length public class Regex4 {
public static void main(String[] args) {
String str = "Danny Doo, Flat no 502, Big Apartment, Wide Road, Near Huge Milestone, Hugo-city 56010, Ph: 9876543210, Email: danny@myworld.com. Maggi Myer, Post bag no 52, Big bank post office, Big bank city 56000, ph: 9876501234, Email: maggi07@myuniverse.com.";
Pattern pattern = Pattern.compile("\\b\\d{5}\\b"); Matcher matcher = pattern.matcher(str); while(matcher.find()) {
System.out.println(matcher.group());
}
}
}
It prints the following:
56010
56000
215