Showing posts with label Enum. Show all posts
Showing posts with label Enum. Show all posts

Thursday, 7 July 2011

java.util.concurrent.TimeUnit ( concurrency )

A TimeUnit represents time durations at a given unit of granularity and provides utility methods to convert across units, and to perform timing and delay operations in these units. A TimeUnit does not maintain time information, but only helps organize and use time representations that may be maintained separately across various contexts.
A TimeUnit is mainly used to inform time-based methods how a given timing parameter should be interpreted. For example, the following code will timeout in 50 milliseconds if the lock is not available:
Lock lock = ...;
if ( lock.tryLock(50L, TimeUnit.MILLISECONDS) ) ...
while this code will timeout in 50 seconds:
Lock lock = ...;
if ( lock.tryLock(50L, TimeUnit.SECONDS) ) ...
Note however, that there is no guarantee that a particular timeout implementation will be able to notice the passage of time at the same granularity as the given TimeUnit.

Not only this it can be used in executor service, to see if there is any timeout or not. 

Although it is part of the java.util.concurrent package, the TimeUnit enum is useful in many contexts outside of concurrency. In this post, I look at how the TimeUnit enum can be used even in code that does not directly deal with concurrent functionality before examining how this enum is an example of many broader concepts in Java development.

Most of us who have probably seen (or implemented, but we'll blame the other developer for it now) code like that shown in the next code listing. In this code listing, a number of provided milliseconds is converted to a whole number of days by dividing by a previously determined single hard-coded number.

/**
    * Convert provided number of milliseconds into number of days
    */
private static long convertMilliSecondsToDaysViaSingleMagicNumber
(final long numberMilliseconds)
{
// 86400000 = 86400 seconds in a day multipled by 1000 ms per second
return numberMilliseconds / 86400000;
}

There are some problems with the approach taken by the above code listing. The most obvious issue may be the use of the magic number 86400000. Although most of us recognize 86400 as the number of seconds in a day, this may not be obvious to everyone and then there's the issue of it being 1000 times greater than that number. The comment in the code listing helps by explaining the underlying meaning of the numbers, but wouldn't it be nice if the code spoke more clearly for itself?

The next code listing shows an arguable slight improvement. Rather than using a single hard-coded number, individual hard-coded numbers are used that are more readable because they are separate. A reader of the code has a better chance of seeing how the number was constructed.

private static long convertMilliSecondsToDaysViaMoreExplanatoryMagicNumbers
(final long numberMilliseconds)  
{
// 60 seconds in minute, 60 minutes in hour, 24 hours in day, and
// one thousand milliseconds in a second
return numberMilliseconds / (60 * 60 * 24 * 1000);
}


Even though the individual numbers might make it easier to see what's happening in the conversion, the comment still might be useful in ensuring that the proper function is understood well. Magic numbers are also still involved and most code analysis tools will report issues with their use. The next code example attempts to deal with the issue of magic numbers.

private final static int NUMBER_MILLISECONDS_IN_SECOND = 1000;
private final static int NUMBER_SECONDS_IN_MINUTE = 60;
private final static int NUMBER_MINUTES_IN_HOUR = 60;
private final static int NUMBER_SECONDS_IN_HOUR =
NUMBER_SECONDS_IN_MINUTE * NUMBER_MINUTES_IN_HOUR;
private final static int NUMBER_HOURS_IN_DAY = 24;
private final static int NUMBER_MINUTES_IN_DAY =
NUMBER_HOURS_IN_DAY * NUMBER_MINUTES_IN_HOUR;
private final static int NUMBER_SECONDS_IN_DAY =
NUMBER_HOURS_IN_DAY * NUMBER_SECONDS_IN_HOUR;
private final static int NUMBER_MILLISECONDS_IN_DAY =
NUMBER_SECONDS_IN_DAY * NUMBER_MILLISECONDS_IN_SECOND;

/**
    * Convert provided number of milliseconds into number of days.
    */
private static long convertMilliSecondsToDaysViaDefinedConstant
(final long numberMilliseconds)
{
return numberMilliseconds / NUMBER_MILLISECONDS_IN_DAY;
}

The approach in the code above is commonly seen in Java code. The "magic" numbers are now defined as constants that can be reused in more than just one place. Although this is arguably an improvement, TimeUnit allows us to make a further improvement to this code.

private static long convertMillisecondsToDaysViaTimeUnit
(final long numberMilliseconds)
{
return TimeUnit.MILLISECONDS.toDays(numberMilliseconds);
}

This code takes advantage of TimeUnit's MILLISECONDS enum constant and toDays(long) method to easily perform this conversion is a standardized and highly readable way. There isn't a magic number in sight!

The above example demonstrates how TimeUnit can be used even when concurrency is not involved. Besides MILLISECONDS, other time unit representations provided by TimeUnit include DAYS, HOURS, MICROSECONDS, MINUTES, NANOSECONDS, and SECONDS. These cover the most commonly used time units one would need.

The methods on the TimeUnit enum allow easy conversion from the unit represented by the enum constant to a different unit of time. There is a general conversion method TimeUnit.convert(long, TimeUnit) that can be used for this purpose. More specific methods are also available for converting to specific types of time units so that the second parameter need not be applied. These methods include the already demonstrated toDays(long) as well as toHours(long), toMicros(long), toMillis(long), toMinutes(long), toNanos(long), and toSeconds(long). Although most of this enum was introduced with J2SE 5, the methods toMinutes(long), toHours(long), and toDays(long) were introduced with Java SE 6.

The enum constants and methods on TimeUnit defined so far are not specifically associated with concurrency and are generally useful. The TimeUnit enum offers three additional methods of interest. TimeUnit.sleep(long) provides a more readable Thread.sleep(long, int). The enum constant of the TimeUnit implies the applicable unit of time, so only a base number needs to be provided. The implication here, of course, is that more obvious numbers can be provided for sleeping rather than needing to worry about expressing a large number in milliseconds or even remembering that the method requires the time be specified in milliseconds.

Two other related useful methods available in TimeUnit are TimeUnit.timedJoin(Thread,long) [convenience method for Thread.join] and TimeUnit.timedWait(Thread,long) [convenience method for Object.wait].

I have used this post to demonstrate how TimeUnit is most obviously useful: it helps developers to write clear code without use of magic numbers for converting between different time measurement units. This is handy in its own right because different APIs often expect different time units. However, TimeUnit has benefits beyond its obvious intended functionality benefits. The TimeUnit enum shows off the power of Java enums and how this power can be leveraged. I look at this next.

Most of us who transitioned from C++ to Java missed having an enum in versions of Java prior to J2SE 5. Fortunately, the wait was worth it as the Java enum is far superior to the C++ enum. There are numerous ways in which the Java enum is better than the C++ enum, but one of the main advantages is the ability to implement methods on the enum. This was shown in the above example where a toDays(long) method allowed for easy conversion of milliseconds via the MILLISECONDS.toDays(long) call. A Java enum is much more than simply an encapsulation of a finite set of integral values. The ability to add behaviors to these enum constants is very powerful.

There are two main approaches for defining methods on an enum. One approach is to define a method at the overall enum level and override it individually at each enum constant's level. The other approach is to implement the method once for the entire enum and all of its enum constants with no need to override the single definition. In other words, one approach is to write an implementation of a method for each enum constant and the other approach writes a method that all the enum constants share. The TimeUnit enum demonstrates both approaches. Its general convert method and all of the convenient toXXXXX methods (where XXXXX are things like Hours or Days) are written specifically for each enum constant and the parent method at the overall enum level throws an AbstractMethodError if not properly overridden by each enum constant (fortunately it always is!). The remaining public methods (timedWait, timedJoin, and sleep) are written with the second approach: a single method implementation exists for each of these that is used by any enum constant defined for TimeUnit.

Besides its usefulness in providing highly readable time unit conversions and besides its usefulness in demonstrating the significant advantages of the Java enum, TimeUnit provides an example of one other "often true" principle in Java: highly and generally useful classes (or enum in this case) can often be found in the SDK where you might least expect it. Although the usefulness of TimeUnit is obvious in concurrent applications, its usefulness goes beyond concurrent functionality. This is not the only case where a more generally useful construct is available in the JDK in a more particular package. I have often seen this in projects I've worked on as well. Often a team will put together a nice class or enum for their own use that is more generally applicable, but which ends up remaining in their rather particular package instead of being in a more generally accessible package.

When we build our own time conversion routines, we typically see hard-coded numbers (or constants defined as) with values such as 1000, 60, and 24. So, it is not surprising that the source code for TimeUnit defines these as constants that it uses in its own conversions. Eventually, the rubber must hit the road and these conversions must take place with these hard numbers. The difference is that use of TimeUnit allows us to have those numbers defined and used outside of our direct code in a well-tested and standardly available enum. It is also interesting to note that hard-coded integers were used in early versions of TimeUnit, but were eventually replaced with internally defined constants:

// Handy constants for conversion methods
static final long C0 = 1L;
static final long C1 = C0 * 1000L;
static final long C2 = C1 * 1000L;
static final long C3 = C2 * 1000L;
static final long C4 = C3 * 60L;
static final long C5 = C4 * 60L;
static final long C6 = C5 * 24L;

This post has been lengthy already. So thanks for bearing :)

Sunday, 17 April 2011

Getting keys from hashtable: Iterating over hashtable

Consider the hashtable:

Hashtable ht = new Hashtable(); 
ht.put("1","One");
ht.put("2","Two");
ht.put("3","Three");

Now getting the keys set can be got as follows:

As a set
Set st = ht.keySet();

System.out.println("Set created from Hashtable Keys contains :");
//iterate through the Set of keys
Iterator itr = st.iterator();
while(itr.hasNext())
System.out.println(itr.next());
Note:
Please note that resultant Set object is backed by the Hashtable.
Any key that is removed from Set will also be removed from
original Hashtable object. The same is not the case with the element addition.
Eg.
st.remove("2");

Getting from enum:
Enumeration e = ht.keys();
while(e.hasMoreElements())
System.out.println(e.nextElement());
}


Tuesday, 12 April 2011

Some points to note about enums

There are few things which could probably be improved in the coming versions of Java.

  • Currently null can be passed as a method parameter or assigned where an enum is expected. A compile-time verification for null enum assignment would probably avoid all those extra null checks that we need to incorporate in our code.
  • Static fields within enums cannot be accessed in its constructor. But, static methods are allowed to be invoked. The compiler enforces verification only for static fields and not methods.
  • However, enum constructors are invoked before static initialization is performed and hence the static fields would not be initialized. So, if you invoke static methods from the constructor which inturn access static fields, they would all be un-initialized.

Serialization of enums

Serialization mechanism ensures that new enum instances are not created on serialization and de-serialization (ensuring singleton behaviour). In a distributed environment when an enum is serialized from one JVM to another JVM, enum's state is not serialized. Hence, it is not encouraged to have state with enums which is updated by the applications.

You can only have constant attributes that are initialized by the constructor.

Eg.

import java.io.Serializable;  

public class Status {

public enum Status implements Serializable{
STATUS_OPEN(0, "open"),
STATUS_STARTED(1, "started"),
STATUS_INPROGRESS(2, "inprogress"),
STATUS_ONHOLD(3, "onhold"),
STATUS_COMPLETED(4, "completed"),
STATUS_CLOSED(5, "closed");

private final int status;
private final String description;

Status(int aStatus, String desc){
this.status = aStatus;
this.description = desc;
}
public int status(){
return this.status;
}
public String description(){
return this.description;
}

}
}

Restrictions on enum types

Though enum types are full-fledged classes, the following are not allowed with enums:

  • enums cannot be subclassed
  • enums cannot have public constructor
  • enums are not allowed to be instantiated (using new)
  • enums cannot be cloned

All of these are enforced during compile-time.

Constant specific methods for enums

If the implementation of methods vary for each Constant, then you can implement the methods specific to a constant.

public enum Color {
RED { public Color complimentary() { return GREEN; }},
BLUE { public Color complimentary() { return ORANGE; }},
YELLOW { public Color complimentary() { return PURPLE; }},
...

public abstract Color complimentary();
}


Each color has its own complementary color and to implement this we can use constant specific methods to return the complementary color. The method complementary() has to be either defined as an abstract method within Color enum or could be a method in one of the implemented interfaces.

Enum : Toc

Pre-java5 enums in java

Java5 - arrival of enum 

Enum with additional fields and custom constructor

Enum with additional fields and custom custructor

Enum that implements interface

Enum and their super class

Constant specific methods for enums

Switch statements on enums

toString() for enums

Convert string to enums

Datastructures related to enums

Restriction on enum types

Serializations of enums

Some points to note about enums

Pre-java 5 style enums

Enumerations already existed in other languages like C, C++, SmallTalk etc. Enums are used primarily to handle a collection of logically grouped constants.
But in java, in prior releases, the standard way to represent an enumerated type was the int Enum pattern:
// int Enum Pattern - has severe problems!
public static final int SEASON_WINTER = 0;
public static final int SEASON_SPRING = 1;
public static final int SEASON_SUMMER = 2;
public static final int SEASON_FALL = 3;

Drawbacks of This Approach:

  • Type Safety: All statuses above may carry some business meaning, but in Java language context, these are just int values. This means any int value is a status for this Java program. So the program using these statuses can break with any int value not defined in this group.
  • Compile Time Constants: All these constants are compiled and used in the program. If you want to add any new constant then you will have to add it to the list and recompile everything.
  • Uninformative: When printed, these are just numbers for a reader. E.g. if a program prints status = 3, the reader will have to go and find out what does it actually mean. Amount of information available with the print is minimal.
  • Restricted Behavior: If you want to use these values in a remote call, or compare them, then you will have to handle it explicitly. Serializable, Comparable interfaces offered by Java for same purpose cannot be used. Also there is no room to add any additional behavior to the statuses, e.g. attaching basic object behavior of hashCode(), toString() and equals() methods.
  • Meaningless Switch-Case Use: When you use statuses above in switch case, you cannot use the variable names; instead you will have to use the meaningless/uninformative numbers to compare. Readability of program goes down considerably in this case.
  • Non-Iterative List: This is a list of values, but you cannot iterate over it the way you can on any collection.
The solution to above problem is Enum data type in Java 5. Concept of Enum is obtained from the counterpart technologies like C, C++, C# etc. and also considering the Typesafe Enum design pattern in Effective Java book by Joshua Bloch:


You can read this pattern here.

Wednesday, 27 October 2010

Related data structure classes: EnumSet and EnumMap

The java.util.EnumSet class provides an efficient implementation of sets of enums as bit maps, or powersets as they were called in Pascal. EnumSet can also generate an Iterable for use with subsets in the for-each statement.
java.util.EnumMap provides an efficient implementation of a map for enums based on an array.

They provide a compact and efficient implementation for enum types. These collections are not synchronized and when used in multi-threaded environment, applications should take care of synchronizing the operations on the collection. EnumMap and EnumSet are homogenous collections of the same enum type. They cannot be used to operate on different enum types at the same time.


public enum Color {
//
RED, BLUE, YELLOW, GREEN, ORANGE, PURPLE;
public static EnumSet<Color> getPrimaryColors() {
return EnumSet.of(RED, BLUE, YELLOW);
}
public static EnumSet<Color> getSecondaryColors() {
return EnumSet.complementOf(getPrimaryColors());
}

public static void main(String[] args) {
System.out.println("Primary Colors: "+Color.getPrimaryColors());
System.out.println("Secondary Colors: "+Color.getSecondaryColors());
System.out.println("Universe: "+EnumSet.allOf(Color.class));
}
}

Convert string to enum

public enum Shape { RECTANGLE, CIRCLE, LINE } 
The valueOf() method can be used to convert a string value to an enum value. Here is an example of reading in a Shape value from a Scanner object in.
drawing = Shape.valueOf(in.next());
or
drawing = Shape.valueOf("RECTANGLE") 
We can have custom methods to deal with this, if we dont want to have some extra customization.
eg. If the text is not the same to the enumeration value:
public enum Blah {
  A
("text1"),
  B
("text2"),
  C
("text3"),
  D
("text4");

 
private String text;

 
Blah(String text) {
   
this.text = text;
 
}

 
public String getText() {
   
return this.text;
 
}

 
public static Blah fromString(String text) {
   
if (text != null) {
     
for (Blah b : Blah.values()) {
       
if (text.equalsIgnoreCase(b.text)) {
         
return b;
     
}
   
}
   
return null;
 
}
}

toString() for Enums

public enum Shape { RECTANGLE, CIRCLE, LINE }
Shape drawing = Shape.RECTANGLE;   // Only a Shape value can be assigned.
System.out.println(drawing);    // Prints RECTANGLE

Override toString method for All Enums
A semicolon after the last element is required to be able to compile it. More details on overriding enum toString method can be found.
public enum Color {
WHITE, BLACK, RED, YELLOW, BLUE; //; is required here.

@Override public String toString() {
//only capitalize the first letter
String s = super.toString();
return s.substring(0, 1) + s.substring(1).toLowerCase();
}
}


Override toString method element by element
The default string value for java enum is its face value, or the element name. However, you can customize the string value by overriding toString() method. For example,
public enum MyType {
ONE {
public String toString() {
return "this is one";
}
},

TWO {
public String toString() {
return "this is two";
}
}
}
Running the following test code will produce this:
public class EnumTest {
public static void main(String[] args) {
System.out.println(MyType.ONE);
System.out.println(MyType.TWO);
}
}
-------------
this is one
this is two
Another interesting fact is, once you override toString() method, you in effect turn each element into an anonymous inner class. So after compiling the above enum class, you will see a long list of class files:
MyType.class
MyType$1.class
MyType$2.class

Enum and their super-class

All java enum E implicitly extends java.lang.Enum. Since java doesn't allow multiple inheritance, enum types can't have superclass. They can't even extend from java.lang.Enum, nor java.lang.Object. It also means enum A can't inherit or extend enum B.

For example, the following is an invalid enum declaration:
public enum MyType extends Object {
ONE, TWO
}
Compiler error:
MyType.java:3: '{' expected
public enum MyType extends Object {
MyType.java:6: expected
2 errors
 
The correct form should be:
public enum MyType {
ONE, TWO
}

Enum that implements interfaces

Enum can implement any interfaces. All enum types implicitly implements java.io.Serializable, and java.lang.Comparable.
public enum Color implements Runnable {
WHITE, BLACK, RED, YELLOW, BLUE;

public void run() {
System.out.println("name()=" + name() +
", toString()=" + toString());
}
}
A sample test program to invoke this run() method:
for(Color c : Color.values()) {
c.run();
}
Or,
for(Runnable r : Color.values()) {
r.run();
}

Enum with additional fields and custom constructor

Enum constructors must be either private or package default, and protected or public access modifier is not allowed. When custom constructor is declared, all elements declaration must match that constructor.
public enum Color { //Color is of type enum
 WHITE(21), BLACK(22), RED(23), YELLOW(24), BLUE(25);
private int code;

private Color(int c) {
code = c;
}

public int getCode() {
return code;
}

Switch statement on enums

public enum Shape { RECTANGLE, CIRCLE, LINE }

The switch statement was enhanced to allow a convenient use of enums. Note that the case values don't have to be qualified with the enum class name, which can be determined from the switch control value.
switch (drawing) {
case RECTANGLE: g.drawRect(x, y, width, height);
break;
case CIRCLE : g.drawOval(x, y, width, height);
break;
case LINE : g.drawLine(x, y, x + width, y + height);
break;
}

Monday, 20 September 2010

Enums in java

In prior releases, the standard way to represent an enumerated type was the int Enum pattern:
// int Enum Pattern - has severe problems!
public static final int SEASON_WINTER = 0;
public static final int SEASON_SPRING = 1;
public static final int SEASON_SUMMER = 2;
public static final int SEASON_FALL = 3;
But these are not type safe, and clearly naming them is bit of a problem.
See here more for details. So in Java 5, they introduced Enums.

Defining Enums
Eg.
enum Season { WINTER, SPRING, SUMMER, FALL } 
public enum Rank { DEUCE, THREE, FOUR, FIVE, SIX,
SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE }

public enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES }
  
public enum Shape { RECTANGLE, CIRCLE, LINE } 
  
Note on Semicolon ( ; )
Enum embedded inside a class. Outside the enclosing class, elements are referenced as Outter.Color.RED, Outter.Color.BLUE, etc.
public class Outter {
public enum Color {
WHITE, BLACK, RED, YELLOW, BLUE
}
}

Declaring enum variables and using enum values

The enum class name can be use like any other class type in declarations. Usually enum values must be prefixed with the enum type name.

Shape drawing = Shape.RECTANGLE;   // Only a Shape value can be assigned.

Looping over all enum values with foreach loop

The static values() method of an enum type returns an array of the enum values. The foreach loop is a good way to go over all of them.

for ( Color c :Color.values() ) {
         System.out.print( c + " " );
}


Getting an integer equivalent of an enum value

Each enum value in an enum class has an associated default value, starting with zero for the first value and incrementing by one for each additional value. This may be accessed with the ordinal() method.
System.out.println(drawing.ordinal());     // Prints 0 for RECTANGLE.
 

Input (Convert string to enum)

The valueOf() method can be used to convert a string value to an enum value. Here is an example of reading in a Shape value from a Scanner object in.
drawing = Shape.valueOf(in.next());
 
or
drawing = Shape.valueOf("RECTANGLE");
 
The static methods valueOf() and values() are created at compile time and do not appear in source code. 
They do appear in Javadoc, though; 
 
Read more in Effective java for better practises.