Coding Standard
Coding Standard
J2EE Consulting
Java Programming
Guidelines and Best
Practices
Version 1.1, April 2006
Table of Contents
1. ................................................................................................................................ Introduction 1
1.1. ............................................................................................................... Purpose and Scope 1
1.2. ........................................................................................................................ Prerequisites 1
1.3. .......................................................................................................................... References 2
2. ....................................................................................................................... Coding Guidelines 5
2.1. ........................................................................................................................ Code Layout 5
2.2. ........................................................................................................... Code Documentation 7
2.2.1................................................................................................... How to Use Javadoc 8
2.3. .................................................................................................................... Code Structure 10
2.3.1.......................................................................................... Derive Packages from Design 10
2.3.2.................................................................................................. General Class Structure 11
2.3.3............................................................................................... Applying Design Patterns 17
2.3.4.............................................................................................. Programming by Contract 19
2.3.5........................................................ Rules for Constructors, Object Creation and Destruction 24
2.3.6........................................................................................................ Rules for Methods 26
2.3.7............................................................................. Methods from java.lang.object and JDK 28
2.3.8................................................................ Hints for Expressions and Control-Flow Structures 34
2.3.9..................................................................................Best Practices in Exception Handling 37
2.4. .............................................................................................. Performance and Optimization 40
3. ................................................................................................. Use of Specific Java Mechanisms 44
3.1.1.................................................................................... Concurrency and Synchronization 44
3.1.2................................................................................................................ Serialization 45
4. ........................................................................... Solutions to Specific Problems, Use of Libraries 46
4.1.1........................................................................ Data Structure Implementation, Collections 46
4.1.2............................................................................................................. Date and Time 53
4.1.3............................................................................................................ String Handling 58
4.1.4...................................................................................................... Regular Expressions 60
4.1.5............................................................................................................... Mathematics 64
Appendix 1...................................................................................................................................... 69
Appendix 2...................................................................................................................................... 70
Revision History
Version and date Change description
Version 1.0, Draft A - May 19, 2006 First issued version
Version 1.1, Final - April 12, 2006 Approved by J2EE Consulting, UBS TA and Java CPM
1. Introduction
The goal is not to replicate existing knowledge, but rather to condense and
concentrate it to a set of rules and guidelines to be consulted during software
development. To avoid reading hundreds of pages or asking many times experts
for help, useful knowledge is presented in form of a quick reference, a kind of
"good Java programming in a nutshell".
In-depth explanations are not part of the guidelines. The reader is urged to
consult the literature for the reasons behind them. This document tries to
organize the existing knowledge and to abstract it into a set of rules for
guidance. References are provided for further reading, in order to satisfy those
readers interested in the rationale behind specific rules and hints.
1.2. Prerequisites
The reader should at least have a previous exposure to programming in general,
and in particular to Java. A basic understanding of object-oriented technology,
as well as of data structures and algorithms is required for a good understan-
ding of the guidelines.
1.3. References
The publications listed below are recommended for further reading. They ser-
ved as basis for the guidelines. The reference [3] is highly recommended as first
lecture.
Among a lot of other ones, the following links contain references to interesting
articles of good quality on Java topics (some are general, others are restricted to
specific topics). It is recommended to visit these sites from time to time.
Ref URL
[URL-1] www.javaworld.com
General articles on Java technologies
[URL-2] www.onjava.com
General articles on Java technologies
[URL-3] www.precisejava.com
Tutorials
[URL-4] java.almanac.com
Examples about the JDK classes
[URL-5] www.crossroads.com/bradapp/javapats.html
community.java.net/patterns
Overview of design patterns
[URL-6] java.sun.com/j2se/1.4.2/docs/guide/lang/assert.html
Introduction to assertions
[URL-7] http://www.regular-expressions.info/index.html
(Web site devoted to regular expressions)
www.regexlib.com (examples)
www.regex.info (an excellent book on REs)
the book presented on this site is
FRIEDL, Mastering Regular Expressions, O'Reilly, 2nd ed.
[URL-7] www2.hursley.ibm.com/decimal
in-depth information about decimal numbers and
floating-point computations
http://java.sun.com/developer/JDCTechTips/2003/tt0204
.html#2
paper about floating-point arithmetic in Java
A lot of books cover the topic of "Software Design Patterns". Among others,
the following are of interest for Java programmers (the first one is the famous
"GoF book"):
Concerning algorithms and data structures, and given the fact that implemen-
tations are available through the Java Collections suite, any book is possibly
suitable for self-teaching, even if not using directly Java.
However, if one wants to see the application of data structures and algorithms
in Java, using the most advanced features of Java 5, the following book is
suitable:
2. Coding Guidelines
The goal is to produce source code which is readable by many persons, not to
define strict numerical values for a single layout attribute (e.g. "indent by 4
spaces"). A consistent layout is an important help in team communication and
a small, but effective step toward "ego-less programming".
Code layout
R.LAY.4 Do not use "hard" tabs, let the editor (or the formatter/beautifier)
replace them by spaces.
Naming conventions
R.NAM.1 Apply the UBS conventions first (see [2]). If a case is not covered by
these conventions, apply the following guidelines. In case of colli-
sions, the UBS conventions must be used.
R.NAM.2 Use meaningful, familiar names, not single letters. Avoid too long
names, but use complete ones.
R.NAM.5 Do not use names that differ only in case or grammatical number
(singular, plural).
R.NAM.10 Use standard names for trivial throwaway variables (but only for
these), to be used in the smallest possible scope (e.g. for
statement). Possible names are as follow:
• character c
• int i
• String s
• Object o
R.NAM.11 Apply the naming conventions for variables to arrays, too. Place the
brackets directly adjacent to the type itself.
R.NAM.13 Use the following prefixes and postfixes for typical classes:
• Use the postfix Action for classes extending the Struts Action
class: <class_name> + Action
Doing so, a bridge between design and implementation can be drawn, which
helps reconstructing the way taken and the technical decisions made during the
transaction from design to code.
General guidelines
R.DOC.2 Write documentation for those who must use your code and those
who must maintain it.
R.DOC.7 Write summary descriptions that stand alone. Omit the subject
when describing actions, subject and verb when describing things.
R.DOC.11 Describe "why" the code is doing what it does, not "what" the
code is doing. That means avoiding redundant comments (such es
i++; // increment by one), concentrating on the explana-
tion of complex algorithms and non-evident solutions.
Code should never be documented to explain what the code is
doing; the code itself already does that. Documentation should
explain why a block of code is doing what it does. Anyone reading
the code should be already familiar with the language used.
Comment structure
R.DOC.14 Provide a summary description for each class, interface, field and
method.
/* package-private */
R.DOC.18 Add internal comments only if they will aid others in understanding
your code. Use one-line comments to explain implementation
details.
Practical hints
R.DOC.19 Avoid the use of end-line comments, but explain local variable
declarations with an end-line comment.
R.JDC.2 Use the summary description and overview for each package (see
chapter "Comment Structure") to generate the package
documentation:
2. The file must contain HTML tags only, but not Java code
5. All Javadoc tags, except for @link, can be used in this text.
Any @see tag must use fully qualified names.
3. Place this file at the top of the source directory hierarchy, and
use the -overview option of the javadoc tool to include it
in the generated documentation
2. Use a single space (no tabs) before the beginning of the text
7. Don't use the <tt> tag, because it is a font tag and the use of
such elements is discouraged in HTML 4.01 in favor of style
sheets
R.CDE.6 Place types2 that are commonly used, changed, and released
together, or mutually dependent on each other, into the same
package. A package consists of classes reused together.
1 A directed graph is a graph with no path that starts and ends at the same vertex. Consult a book
General advices
R.CDE.10 Always use the same declaration order for a class body.
Two possible sequences are meaningful:
3 The Open-Closed Principle (defined by Bertrand Meyer in 1988) is one of the fundamental
type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1
is substituted for o2 then S is a subtype of T".
5
This design is called composition because the existing class becomes a component of the new
one. Each instance method in the new class invokes the corresponding method of the contained
instance and returns the results. This is known as forwarding. Sometimes, this combination is
called delegation. Hower, in a delegation, the wrapper object passes itself to the wrapped object
(see GoF for further details).
R.CDE.16 Define small classes and small methods. Replace repeated non-
trivial expressions with equivalent methods. Factor out common
functionality.
R.CDE.17 Apply refactoring, and put common code either in helper classes, if
they are not intimately bound to the class using them.
If there is a strong relationship between class and helper class,
which makes the use of the helper class only meaningful when
close to the use of the class itself, use an inner class:
If the inner class is not declared as static, it has full access to private
attributes and methods of the enclosing class.
Interfaces
6
Look at http://java.sun.com/j2se/1.5.0/docs/guide/language/generics.html for a first introduction
to the topic.
R.CDE.19 Interfaces are generally public, sometimes with package scope (no
modifier). Don't use static or abstract modifiers, because they
are redundant. Method declarations in interfaces are by definition
public (but are restricted to package visibility if the interface itself
has package visibility).
R.CDE.21 Use a marker interface to signal that any class implementing this
interface has the same property.
R.CDE.22 Avoid name clashes in interfaces (methods with the same name in
different interfaces).
Immutability
{
private <NON_IMMUTABLE> core;
public get<ATTRIBUTE>()
{
return core.get<ATTRIBUTE>();
}
}
Import declarations
R.CDE.26 Keep import declarations ordered. Use the following order: first the
Java packages (java.<package>, javax.<package>), then
the packages from other products (com.<package>).
The application-specific packages follow at the end of the import
list. Subpackages (<package>.<subpackage>) should directly
follow the corresponding package declarations.
Constants
R.CDE.30 Don't use interfaces only to define and collect constants. Interfaces
are for types only (see [3]).
Apply the following rules:
The following code example shows the basic template for an enu-
meration class. Each single element of the enumeration (which
corresponds mathematically to a set), is realized as pre-instantiated
class.
Usage:
o declaration:
<METHOD>( <NAME> enum-element );
o call sequence:
<CLASS>.<METHOD>( <NAME>.<CONSTANT_n> );
public final class <NAME>
{
// set of constants 1..n
public static final <NAME>
<CONSTANT_1> = new <NAME>(…);
…
public static final <NAME>
<CONSTANT_n> = new <NAME>(…);
// internal structure
private transient <TYPE> <ATTRIBUTE>;
private <NAME>(…) { … }
{
return super.hashCode();
}
{
<ATTRIBUTE> = <VALUE>;
…
}
For further information, please consult the literature reference at the beginning
of the document (items [D-1] to [D-4]).
• Not all patterns are simple to use and are free of side effects.
Some should be used with care, because of technical conse-
quences (consider the Singleton pattern in distributed environ-
ments) or implications (security, unwanted flexibility, complicated
code).
• A pattern can be used the wrong way. The idea can be misunder-
stood, or it can be wrongly implemented.
Adapter Pattern
Command Pattern
anObject.doThis().doThat().andThis();
Singleton Pattern
R.PAT.5 Apply the "once and only once" principle, which requires a positive
answer to all three questions8:
• Will every application use this class exactly the same way?
• Will every application ever need only one instance of this class?
8 See the chapter "When it really is a singleton" in the paper "Use singletons wisely" (URL:
throws ObjectStreamException
{
return INSTANCE;
}
}
R.PAT.7 Design patterns such as Strategy and Visitor should be used only
with good reasons. Visitor is a quite complex pattern, whose imple-
mentation raises the issue of accessibility of the visited part.
Strategy provides algorithmic flexibility, but can lead a functional
style of programming. The decision about the choice of the algo-
rithm requires some kind of logic and thus some pre-existent infor-
mation. The source of it (and their availability) has to be considered
during design, but it is also an issue of analysis.
Use a plug-in algorithm when:
Flyweight Pattern
10
URL: http://java.sun.com/developer/technicalArticles/Programming/singletons/
11
"Programming by Contract" is explained in depth in the book of B. Meyer, "Object-oriented
Software Construction" (Prentice-Hall, 1997, 2nd edition, ISBN 0-13-629155-4).
a contract between client and service provider, helps clarifying basic issues such
as required input, delivered results and internal state changes. Even if assertions
are simply recorded as comments, they are part of the documentation and help
fulfilling the requirements on the software.
R.EXC.1 Consider each method as a contract between the caller and the
callee. The contract states the caller must abide by the precondi-
tions of a method and the method, in turn, must return results that
satisfy the postconditions associated with the method. Additionally,
an invariant is a condition that must always hold true for an object.
R.EXC.5 Use the full form of assert, which allows you to implicitly document
the assertion by passing an appropriate message to
AssertionError:
R.EXC.6 In assert, don't use operations which change the object state
through side effects. The assertion should never touch the object
itself. It must be possible to run the system with or without asser-
tions, without incurring in unexpected state changes.
If it is necessary to save some data prior to a state change in a
postcondition, use two assert statements and an inner class:
AssertionData data;
12 The assertion mechanism is available in Java 1.4 and upward. In earlier versions, it can be
switch (<VAR>): …
default: assert false : <VAR>;
R.EXC.9 In Java 1.4 and upwards13, use the built-in assertion mechanism.
This mechanism can be enabled and disabled as needed, without
changing the code.
o –enableassertions (-ea)
o –enableassertions:PACKAGE (-ea:PACKAGE)
o –enableassertions:CLASS (-ea:CLASS)
o –enablesystemassertions (-esa)
o Click Apply.
In Eclipse/RAD, go to Run->Run...
13
See footnote to R.EXC.2
o Click Run.
o setClassAssertionStatus
( String packageName, boolean enabled)
Be aware that the settings will only apply to classes that the
class loader has not yet loaded into the VM.
Using
static
{
ClassLoader.getSystemClassLoader().
setDefaultAssertionStatus( true );
}
does not provide a real guarantee that all classes will be loaded
with assertions enabled.
To ensure that some code doesn't execute without assertion
checking, use the following idiom:
static
{
boolean assertsEnabled = false;
assert assertsEnabled = true;
if ( !assertsEnabled )
throw new RuntimeException( … );
}
R.CST.5 Use the same name for input parameters and their corresponding
attributes. Qualify the latter ones with this:
R.CST.11 If the class implements an interface, assign the object reference ob-
ained from the new operator to a variable of the interface type, not
the class type (e.g. List list = new ArrayList();). Doing
this decouples the code using the list from the concrete implemen-
tation.
However, if the implementation offers specific methods not descri-
bed by the interface, and such methods can be useful in a given
context, the implementation should be used instead. In the case of
ArrayList, the method trimToSize() is not part of the List
interface. If this method is used, list should be instantiated as
ArrayList list = new ArrayList();
R.CST.14 Don't create a new object when an existing one should be reused.
But don't reuse an existing object when a new one should be
created (e.g. defensive copy).
If a class has several set<attribute>(<type> attribute)
methods, consider the possibility of a reinitialize() method
to reuse the object.
R.CST.16 Avoid building an own object pool. Don't manage memory yourself.
This rule applies for every kind of object, including database con-
nections and threads. In the J2EE context, pooling is best done by
the container itself – rely on this mechanism.
R.MET.3 For parameter types (both as input to a method and as output from
a method), favor interfaces over classes.
R.MET.4 Avoid long parameter lists. Use helper classes (with static methods)
to hold aggregates of parameters. This is especially recommended if
a frequently occurring sequence of parameters represent some
distinct entity. A special case of this situation is the so-called Data
Transfer Object pattern (see [2]).
• IllegalArgumentException
• IndexOutOfBoundsException
• NullPointerException.
R.MET.14 Delay work that has a good chance of never needing to be done.
To meet your performance goals, avoid unnecessary computations.
Apply lazy evaluation:
<METHOD>()
{
if ( <ATTRIBUTE> == null )
{
// set to valid value
}
return <ATTRIBUTE>;
}
equals()
Skeletal implementation:
14
The cost function is a function of input prices and output quantity. Its value is the cost of ma-
king that output given those input prices. The term is taken from economic theory and used in
computing science for analysis of time behavior of data structures and algorithms.
hashCode()
boolean (f ? 0 : 1)
float Float.floatToIntBits(f)
double Double
.doubleToIntBits(f)
Skeletal implementation:
15 The >>> operator defines an unsigned right shift. It has the same semantics as the >> operator,
except that it always shifts zeros into the high-order bits of the result, regardless of the sign of the
left-hand operand. This technique is called "zero extension" and is appropriate when the left
operand is being treated as un unsigned value.
toString()
compareTo()
a) symmetry:
sgn( x.compareTo(y)) ==
-sgn(y.compareTo(x))
b) transitivity:
x.compareTo(y) > 0 && y.compareTo(z) > 0
x.compareTo(z) > 0
additionally: x.compareTo(y) == 0
sgn(x.compareTo(z)) ==
sgn(y.compareTo(z))
c) equality:
(x.compareTo(y) == 0) == x.equals(y)
• The contract for compareTo() specifies only the sign, not the
magnitude of the return value. Although the common practice
is to use -1 for "less", 1 for "greater" and 0 for "equal",
values other then 1 can be used. One possibility is to build
arithmetical differences (e.g. value of attribute 1 - value of
attribute 2) in order to signal the possible difference between
attributes. This solution is efficient, but care must be taken not
to overflow the numerical range (the numerical value of the
difference between two integers must be less or equal than 231
- 1)
Skeletal implementation:
public int compareTo( Object o )
{
<C> c = (<C>) o;
…
// check fields
…
return value; // range ::= {-1,1,0}
}
clone()
16
Contrarly to some strange assumption floating around, a copy constructor has nothing to do
with C++. It was there long before such a language was created, coming from the Smalltalk
heritage.
return clone;
}
catch( CloneNotSupportedException e )
{
throw new InternalError();
}
}
return clone;
}
catch( CloneNotSupportedException e )
{
throw new InternalError();
}
}
It is possible to use && and || instead of & and | . In the first case,
the second operation will be computed only if required (according
to rules of mathematical logic). This conditional evaluation is called
"short circuiting" and is applied as follow:
// wrong
if ( a.toLowerCase().equals( b.toLowerCase()) )
// correct
if ( a == b || a.equalsIgnoreCase( b ) )
Loops
R.FLW.7 Code a break statement for the last case (even if it is the default
case) of a switch statement.
But beware that a final break statement is unreachable, if a
return statement follows the default statement:
switch( … )
{
case …: …; break;
case …: …; break;
default : return <VALUE>; break;
}
R.FLW.8 Remember that the break statement breaks out of the current
loop. If there is an outer loop, it will still run. This is possibly not the
intention of the programmer. The same applies to the continue
statement.
RESTART:
{
for ( … )
{
for ( … )
{
// body
break RESTART;
// body
}
}
}
PROCESS:
{
for ( … )
{
for ( … )
{
// body
continue PROCESS;
// body
}
}
}
R.FLW.11 Extract invariants from loops: method calls which deliver the same
result during the whole loop execution should be called only once
before the loop and the result should be stored in a local variable.
try
{
for ( … )
{
// BODY
}
}
catch( IndexOutOfBoundsException e )
{
// ignore
}
Other
General rules
R.CSY.4 Use assertions to catch logical errors in the code. Consult the
chapter about programming by contract in this document for
further information about assertions and their use.
R.CSY.8 In a layered architecture, the exceptions of the lower layer will need
to be caught and handled, or else they must be converted into
exceptions applicable in the higher layer.
Implementation rules
R.CSY.10 It could possibly make sense to separate the fatal error conditions
from the recoverable ones. In order to avoid a lot of exception
classes, reduce the overall number of exceptions by categorizing
try { … }
catch(Recoverable<X>Exception e )
{
<CODE> code = e.getReasonCode();
// act appropriately, according to code
}
R.CSY.11 Avoid using try-catch on a per method basis for all methods
within a block.
17
See http://java.sun.com/docs/books/tutorial/essential/exceptions/runtime.html about Exception
and RuntimeException.
and should contain class name, method name and a symbol which
shortly identifies the exception cause.
<CLASS> class;
try
{
class = (<CLASS>) object;
}
catch( ClassCastException e )
{
…;
}
is preferred over:
<CLASS> class;
if ( object instanceof <CLASS> )
{
class = (<CLASS>) object;
}
else
{
…;
}
R.CSY.22 The reuse of exceptions is not really useful. The information about
the stack trace is not available, because it is generated when the
exception is thrown at execution time.
Example:
18
Thrown when a thread is waiting, sleeping, or otherwise paused for a long time and another
thread interrupts it using the interrupt method in class Thread.
}
catch( … ) { … }
• Ask yourself exactly what the application is doing and why. Then
question whether it needs to do in that way, or even if it needs to do it
at all.
• Apply strategies that do not require changing the source code (e.g.
initial heap size of the Java VM).
• Use tools for perfomance analysis, profiling and code path coverage.
• Measure and verify! Profile the code and look at methods that
consume most of the CPU time, and excessive short-lived object
creation.
Do not optimize code unless you have proved that optimization is necessary.
After performing an optimization, profile again to prove that it has the desired
effect. Each set of changes should be followed by a run of benchmarks to pre-
cisely identify improvements (or degradations!) in the performance across all
functions.
1. Stepwise replacement
Identify the bottlenecks in the code, and replace code fragments, methods
or whole class implementation by more performant versions. Introduce
small changes at once, and measure the performance before and after the
replacement.
2. Use of specific solutions offered by the Java JDK (see also the chapter
"Solutions to Specific Problems, Use of Libraries").
2.2. If there is a need to represent data with many boolean value (e.g. a
statistical survey of market data), use java.util.BitSet.
Although BitSet operations are slower than assignments to
boolean variables, a tiny BitSet with a single-element array can re-
present 64 states (because it uses internally an array of long, and a
long is 64 bits wide) and is usually very efficient.
2.3. Don't use String or StringBuffer for any task that involves
looping over the characters of a string. Instead, use character arrays
directly. Obtain the array using the toCharArray() method, and
after processing convert the array back to String using the methods
valueOf(char[] data) or copyValueOf(char[] data) in
the String class.
2.4. Don't use for the + operation for string concatenation, use
StringBuffer.append() instead. See chapter "String Handling"
for further informations on strings.
2.5. Generally, the JDK methods that convert objects and data types to
strings are suboptimal. Alternative implementations can be
considered19.
2.7. Prefer int over long, prefer float over double (if the range is
sufficient).
to UBS Solution Life Cycle. It could be then be integrated into the Common Lib
suite of public available libraries.
Remove code which is never used and never reached by the control
flow.
String s =…;
for (int i = 0; i < s.length(); i++ ) { … }
instead use:
String s =…;
int l = s.length();
for (int i = 0; i < l; i++ ) { … }
• The thread stack can be reduced if the application doesn't use threads.
A default of 1MB is large, in such a case 256K can be used instead.
o The same is true for the increment (++) and decrement (--)
operators, which are not atomic. They represent a consecutive
read and write operation.
3.1.2. Serialization
R.CSY.9 Consider using Externalizable rather then Serializable,
especially for complex object structures involving the serialization of
deep object graphs or if performance is the primary concern.
Serialization can be improved by turning offf the standard serializa-
tion format. By declaring the class Externalizable instead of
Serializable, and implementing the two methods
readExternal() and writeExternal(), one can control the
serialization process by manipulating the streams (input, output)
directly.
See the appendix "Data Structures" for more information on runtime behavior.
General Issues
R.COL.1 If data structures are needed, consider the ones offered by the
Collection package as the first choice. Avoid implementing own
data structures.
Example:
Collections.sort( list,
String.CASE_INSENSITIVE_ORDER );
20
"Orthogonal" (a term taken from geometry) means in this context that the algorithm can
operate on any type of collection, that is, it is not bound to a single, specific collection.
21 The sorting algorithms in the Arrays and Collections classes are stable, that is, they do not
22 In partial ordering, a comparator does not use all of the instance variables for comparison.
23 In total ordering, the same set of instance variables is used in equals() and in compareTo().
{
Comparable firstComparable =
(Comparable) first;
Comparable secondComparable =
(Comparable) second;
return secondComparable
.compareTo( firstComparable );
}
};
• addAll( Collection c )
Adds all of the elements in the specified collection to this
collection.
• retainAll( Collection c )
Retains only the elements in this collection that are contained
in the specified collection.
• removeAll( Collection c)
Removes all this collection's elements that are also contained in
the specified collection.
• does the first map contain all of the elements in the second
map?
List list =
new ArrayList( Collections
.nCopies( COUNT_VALUE ) );
• Iterator
• Enumeration
Operations on arrays
if ( map.containsKey( key ) )
{
map.remove( key );
}
R.COL.18 Use the following idiom to iterate over all elements of a Map:
R.COL.19 Sets are not ordered (as in mathematical set theory), but implemen-
tations of the SortedSet interface, such as TreeSet, maintain
their elements in ascending sorted order. To this purpose, the ele-
ments must implement the Comparable interface or a Compara-
tor must be used when creating the sorted set.
If the container is required to maintain the order in which elements
are added, one of the general-purpose List implementations
should be used.
R.COL.20 A List and a Set cannot be equal even if they contain exactly the
same elements, because sets are unordered. Maps are not equal if
any of the keys map to different values, even if they contain exactly
the same keys.
To known if two maps have the same set of keys, use
a.keySet().equals( b.keySet() )
The same can be done using the values() method.
• the smaller the table is, the fewer the index values, the more
likely a hash collision
• the larger the table is, the more memory is wasted and the
longer it takes to iterate over a collection view of the map.
R.COL.22 Use higher capacity and lower load factors in HashMap. This will
increase search performance, at the expense of increased space.
Guidelines:
• The smaller the table is, the fewer the index values, the more
likely a hash collision.
• The larger the table is, the more memory is wasted and the
longer it takes to iterate over a collection view of the map
• When using an exact initial size (e.g. for fixed lookup tables),
set the load factor to 1.0 .
R.COL.23 When using strings as keys in a hash table, use a specific class
instead of the general purpose String class. The class itself is
smaller in terms of memory and the retrieval operations will be
faster, because the hash code is already computed.
If the string space of the keys is really stable, consider using the
intern() method of the String class:
R.COL.24 How to implement set operations (in the mathematical sense) using
Set:
24
The load factor LF is used to rehash the table when LF% of the total capacity of reached.
// subset of a set
boolean isSubset =
secondSet.containsAll( firstSet );
• union: a.putAll( b );
• intersection: a.keySet()
.retainAll( b.keySet() );
• submap: a.keySet()
.containsAll( b.keySet() );
R.COL.28 If the order of the elements is revelant, use a List. Such a col-
lection keeps the elements in the order they are inserted (using
add()).
R.COL.29 Use ArrayList for random access, use LinkedList when ad-
ding or removing elements from or to the beginning or the middle
of the list.
String s[] = { … };
Arrays.sort( s );
List list = Arrays.asList( s );
R.COL.32 Lists are not equal unless the elements are in the same order.
list.addAll( Collections
.nCopies( 1000, null ) );
java.sql.Timestamp ts = …;
Date d = new Date( ts.getTime() +
ts.getNanos()/1000000 )
R.DTM.3 The java.util.Date class should not be used directly (nearly all
of its methods are deprecated). Use GregorianCalendar
instead. Note that this class implements the interface Calendar,
allowing you to use the known idiom:
import java.util.*;
import java.text.*;
25
The Unix epoch is the time 1970-01-01T00:00:00Z (in ISO 8601 format).
26 1 nanosecond corresponds to 10[9 seconds.
27 It follows the equivalence 1 millisecond = 1 * 106 nanos.
28
A similar solution can be derived for time and timestamp.
if ( milliseconds < 0 )
throw new IllegalArgumentException(…);
29
At least as of January, 2006. No plans for other implementations are known until yet.
long days;
c1.clear( Calendar.MILLISECOND );
c1.clear( Calendar.SECOND );
c1.clear( Calendar.MINUTE );
c1.clear( Calendar.HOUR_OF_DAY );
c2.clear( Calendar.MILLISECOND );
c2.clear( Calendar.SECOND );
c2.clear( Calendar.MINUTE );
c2.clear( Calendar.HOUR_OF_DAY );
while ( c1.before( c2 ) )
{
c1.add( Calendar.DATE, 1 );
days++;
}
long months;
c1.clear( Calendar.MILLISECOND );
c1.clear( Calendar.SECOND );
c1.clear( Calendar.MINUTE );
c1.clear( Calendar.HOUR_OF_DAY );
c1.clear( Calendar.DATE );
c2.clear( Calendar.MILLISECOND );
c2.clear( Calendar.SECOND );
c2.clear( Calendar.MINUTE );
c2.clear( Calendar.HOUR_OF_DAY );
c2.clear( Calendar.DATE );
while ( c1.before( c2 ) )
{
c1.add( Calendar.MONTH, 1 );
days++;
}
Calendar birthday = …;
Calendar today = Calendar.getInstance();
int age = today.get( Calendar.YEAR ) -
birthDate.get( Calendar.YEAR );
birthday.add( Calendar.YEAR, age );
if ( today.before( birthDate ) )
{
age--;
}
Calendar local = …;
Calendar other = new GregorianCalendar(
TimeZone.getTimeZone( "<TIMEZONE>" ) );
other
.setTimeInMillis( local.getTimeInMillis() );
Calendar local = …;
local
.setTimeInMillis( other.getTimeInMillis() );
calendar
.getActualMaximum( Calendar.DAY_OF_MONTH );
• the idiom mentioned above for the day in the week can be applied to
other date units, such as
Calendar.DAY_OF_MONTH,
Calendar.DAY_OF_WEEK_IN_MONTH,
Calendar.DAY_OF_YEAR
buffer.append( stringList[stringCount] );
return buffer.toString();
}
conversions, try to find out why they are needed. One case is
comparing input against available data, possibly from a database.
The solution could be to use a canonical form and to compare
against it. Another possibility is to define simple helpers, which use
the internal character array fro string processing.
StringBuffer buffer =
new StringBuffer( a.length() + b.length()
+ … + z.length() );
return true;
}
There is no standard for the syntax of REs. Although many elements are com-
mon, different flavors exist.
31 Known abbreviations: RE, regexp, regex, or regxp, with plural forms regexps, regexes, or
regexen.
32 The origins of regular expressions lies in automata theory and formal language theory. See
http://en.wikipedia.org/wiki/Regular_expression for a good and short introduction. The book men-
tioned in [URL-7] is an excellent traitment of the subject.
33
A tutorial about the RegEx package is available from Sun:
http://java.sun.com/docs/books/tutorial/extra/regex/index.html .
The Java version builds on the widely understood Perl 5 regular expression
syntax34, with some documented restrictions. The package consists of two
classes (Pattern and Matcher) and an exception (PatternSyntax-
Exception).
Position markers are used to demand that certain characters occur in a certain
position:
All special characters can be escaped, that is returned to their original meaning
as in the alphabet, by preceding them with a backslash (e.g. \$ means the cha-
racter representing the dollar). The backslash itself is represented by \\ .
Regular expressions are strings containing two kind of characters: literal charac-
ters and meta characters. "Literal" means "taken as it is", and "meta"36 stands
here for "hidden meaning of the character". Meta characters carry additional
information about the characters to be matched in the candidate string.
the regular expression. This form is more efficient in terms of processing than the visible string
representation.
36 "meta" comes from Ancient Greek and is a prefix (not a word on its own) which means
"behind" or "hidden". Meta implies the part of something that is not immediately visible, is in the
background, but which is there nonetheless and has an effect..
\0MNN character with octal value MNN; 0 <= M <= 3, 0 <= N <= 7
The first kind of meta characters is the character class, which matches charac-
ters as elements of a set of characters that share some property:
hint: if hyphen ('-') and/or caret ('^') are part of the search
set, place the hyphen itself at the very beginning, and the caret
at the very end of the RE
[^X-Y] all characters excepted for the set [X-Y]37
(see hint above)
37
In terms of set theory: the complement of the set described by [X-Y] with respect to the universe
of discourse.
38
The set of whitespace characters is composed by space, tab, newline, form feed, carriage return.
The other meta characters are quantifiers. They quantify the previous charac-
ter's significance, by adding the concept of quantity to it. Quantifiers can be
applied of subexpressions; a part of a complete RE is delimiter by parenthesis
(e.g. (RE) ) or by a character set ([x-y]) or by a character class ({alpha}).
Notation Quantifier
? minimum 0 occurrences, maximum 1 occurrence
hint: this quantifier makes the previous character/group optional
+ minimum 1 occurrence, maximum unlimited
hint: this quantifier makes the previous character/group required
* minimum 0 occurrences, maximum unlimited
hint: this quantifier makes the previous character/group optional
{n} requires the previous character/group exactly n times
Additionally, the Matcher provides Boolean methods which test the pattern
on the candidate string, for exemple lookingAt() .
The find() method of Matcher looks for a substring that matches the RE,
starting at the beginning of the input string and returning true if one is
found. Sequential calls to find() will find each successive matching substring.
After a successful match, the start() and end()methods can be used to
find the index of the beginning and of the end of the substring. The group()
method retrieves the actual matching substring.
R.REX.1 Starting from Java 1.4, use the java.util.regex package, not
other solutions outside the JDK.
R.REX.2 Test39 carefully the REs during development, trying to cover special
and unusual cases.
Remember that the engine used in the java.util.regex
package is by default "greedy", which means that the matcher
returns the longest match possible. To do non-reedy matching, a
question mark (?) must be added to the quantifier.
// greedy quantifiers
match = find("A.*c", "AbcAbc"); // AbcAbc
match = find("A.+", "AbcAbc"); // AbcAbc
// non-greedy quantifiers
match = find("A.*?c", "AbcAbc"); // Abc
match = find("A.+?", "AbcAbc"); // Abc
4.1.5. Mathematics
For a good overview of the current work in numerics for Java, consult
http://math.nist.gov/javanumerics, afocal point for information on numerical
computing in Java.
General issues
R.MAT.1 The Math class offers basic math functions, but no statistics. The
companion class StrictMath has the same set of methods, and
ensures that the operations will deliver the same results on all
platforms. As with the modifier strictfp ("strict floating-point"),
there is no increase in numerical precision, but only the guarantee
that the results are not platform-dependent. "strictfp" means
"strict according to the IEEE standard". The goal is to reach better
performance, where strict reproducibility is not required. Please
39
Because the Java implementation follows Perl's syntax (with some restrictions), it is possible to
test the RE online at http://www.quanetic.com/regex.php .
R.MAT.3 Avoid float and double if exact results are required. Consider
using BigDecimal or commercial mathematical libraries instead.
R.MAT.5 Never compare real numbers (in Java: float or double) for
equality. Use only "less than" and "greater than" for comparisons.
R.MAT.6 Cast operations on numerical data types (and byte) don't generate
errors. Values outside the legal range are turned to other (wrong)
values during casting.
This behavior can generate very subtle problems, especially in JDBC
programming, because many drivers do not check for illegal results
from cast operations.
Examples:
int n = 100;
byte b = (byte) n; // ok, range [-127,+128]
int m = 200;
byte c = (byte) m; // wrong, value is -56
double d = 0.3;
BigDecimal bd
= new BigDecimal( Double.toString( d ) );
bd.setScale( scale, BigDecimal.ROUND_HALF_UP );
sqlStatement.setBigDecimal( columnIndex, bd );
Utilities
40 Java 1.4 and higher offers a Currency class representing all world currencies.
long l = Math.round( d );
double d = Math.rint( d );
R.MAT.10 For integer values, the max, min, abs functions can be implemented
by simple on-liners:
int max = (a > b) ? a : b;
int min = (a > b) ? b : a;
int abs = (j > 0) ? j : -j;
R.MAT.13 If you need to generate random integers between high and low,
use the following idiom:
Use of BigDecimal
41
In fixed-point computations, the number of fractional digits is a fixed constant.
Appendix 1
Basic information about floating-point arithmetic
In both cases, the significand and the exponent are integers. Therefore, whole
integer values can be represented exactly in any integer base. In contrast, the
set of fractional values that can be represented exactly by a finite number of
digits (as it is the case on a computer), varies by base.
Examples
Numerical properties
bits 24 53 ---
decimal digits 6 to 9 15 to 17 1 to
billions
Appendix 2
Data Structures
For further information, please consult the literature reference at the beginning
of the document (item [A-1]).
addFirst(o) O(1)
removeFirst() O(1)