Tuesday, November 30, 2010

Stringifying Java Arrays

J2SE 5 provided significant new language features that made Java significantly easier to use and more expressive than it had ever been. Although "big" new J2SE 5 features such as enums, generics, and annotations, there was a plethora of new APIs and methods that have made our lives easier ever since. In this post, I briefly look at two of my favorites when dealing with Java arrays: the Arrays.toString(Object[]) method and the Arrays.deepToString(Object[]) method.

The Arrays class has been around since JDK 1.2, but the methods for conveniently and simply converting arrays to a readable String including relevant array content without using Arrays.asList() were added with J2SE 5. Both Arrays.toString(Object[]) and Arrays.deepToString(Object[]) are static methods that act upon the arrays provided to them. The former, Arrays.toString(Object[]), is intended for single-dimension arrays while the latter, Arrays.deepToString(Object[]), is intended for multi-dimensional arrays. As my example later in this post will demonstrate, the multi-dimension deepToString will produce expected results even for single-dimension arrays. The two methods also provide easy and safe null handling, something that I appreciate.

The next code listing is for a simple demonstration class that demonstrates trying to put the contents of various types of Java arrays into a String format. The types of arrays demonstrated are a single dimension array, a double dimensional array representing multi-dimensional arrays of various sizes, and an array that is really just null. The three methods demonstrated for getting a String out of these three types of arrays are (1) simple Object.toString() on each array (implicitly in case of null array to avoid the dreaded NullPointerException), (2) Arrays.toString(Object[]), and (3) Arrays.deepToString(Object[]).

ArrayStrings.java
package dustin.examples;

import java.util.Arrays;
import static java.lang.System.out;

/**
 * Simple demonstration of Arrays.toString(Object[]) method and the
 * Arrays.deepToString(Object[]) method.
 */
public class ArrayStrings
{
   /**
    * Demonstrate usage and behavior of Arrays.toString(Object[]).
    */
   private static void demonstrateArraysToString()
   {
      printHeader("Arrays.toString(Object[])");
      out.println(
           "Single Dimension Arrays.toString: "
         + Arrays.toString(prepareSingleDimensionArray()));
      out.println(
           "Double Dimension Arrays.toString: "
         + Arrays.toString(prepareDoubleDimensionArray()));
      out.println(
           "Null Array Arrays.toString: "
         + Arrays.toString(prepareNullArray()));
   }

   /**
    * Demonstrate usage and behavior of Arrays.deepToString(Object[]).
    */
   private static void demonstrateArraysDeepToString()
   {
      printHeader("Arrays.deepToString(Object[])");
      out.println(
           "Single Dimension Arrays.deepToString: "
         + Arrays.deepToString(prepareSingleDimensionArray()));
      out.println(
           "Double Dimension Arrays.deepToString: "
         + Arrays.deepToString(prepareDoubleDimensionArray()));
      out.println(
           "Null Array Arrays.deepToString: "
         + Arrays.deepToString(prepareNullArray()));
   }

   /**
    * Demonstrate attempting to get String version of array with simple toString()
    * call (not using Arrays class).
    */
   private static void demonstrateDirectArrayString()
   {
      printHeader("Object[].toString() [implicit or explicit]");
      out.println("Single Dimension toString(): " + prepareSingleDimensionArray().toString());
      out.println("Double Dimension toString(): " + prepareDoubleDimensionArray());
      out.println("Null Array toString(): " + prepareNullArray());
   }

   /**
    * Prepare a single-dimensional array to be used in demonstrations.
    *
    * @return Single-dimensional array.
    */
   private static Object[] prepareSingleDimensionArray()
   {
      final String[] names = {"Aaron", "Bianca", "Charles", "Denise", "Elmer"};
      return names;
   }

   /**
    * Prepare a double-dimension array to be used in demonstrations.
    *
    * @return Double-dimensional array.
    */
   private static Object[] prepareDoubleDimensionArray()
   {
      final Object[][] namesAndAges = {
         {"Aaron", 10}, {"Bianca", 25}, {"Charles", 32}, {"Denise", 29}, {"Elmer", 67}};
      return namesAndAges;
   }

   /**
    * Prepare a null array.
    *
    * @return Array that is really null.
    */
   private static Object[] prepareNullArray()
   {
      return null;
   }

   /**
    * Print simple header to standard output with provided header string.
    *
    * @param headerString Text to be included in simple header.
    */
   public static void printHeader(final String headerString)
   {
      out.println(
         "\n===================================================================");
      out.println("== " + headerString);
      out.println(
         "===================================================================");
   }

   /**
    * Main executable function for demonstrating Arrays.toString(Object[]) and
    * Arrays.deepToString(Object[]) methods.
    */
   public static void main(final String[] arguments)
   {
      demonstrateDirectArrayString();
      demonstrateArraysToString();
      demonstrateArraysDeepToString();
   }
}

The above code exercises the three mentioned approaches for getting a String out of an array on the three different types of arrays: single dimension, multi dimension, and null array. The output from running this code demonstrates the utility of the different approaches. That output is shown next.

===================================================================
== Object[].toString() [implicit or explicit]
===================================================================
Single Dimension toString(): [Ljava.lang.String;@3e25a5
Double Dimension toString(): [[Ljava.lang.Object;@19821f
Null Array toString(): null

===================================================================
== Arrays.toString(Object[])
===================================================================
Single Dimension Arrays.toString: [Aaron, Bianca, Charles, Denise, Elmer]
Double Dimension Arrays.toString: [[Ljava.lang.Object;@addbf1, [Ljava.lang.Object;@42e816, [Ljava.lang.Object;@9304b1, [Ljava.lang.Object;@190d11, [Ljava.lang.Object;@a90653]
Null Array Arrays.toString: null

===================================================================
== Arrays.deepToString(Object[])
===================================================================
Single Dimension Arrays.deepToString: [Aaron, Bianca, Charles, Denise, Elmer]
Double Dimension Arrays.deepToString: [[Aaron, 10], [Bianca, 25], [Charles, 32], [Denise, 29], [Elmer, 67]]
Null Array Arrays.deepToString: null

The code above and its corresponding output lead to several observations:
  1. Simple Object.toString() on arrays is seldom what we want as it only prints the String representation of the array itself and not of its contents.
  2. Arrays.toString(Object[]) will print a String representation for multi-dimensional arrays, but this representation suffers the same drawbacks as Object.toString() after the first dimension. The first dimension (and only dimension for a single dimension array) gets put into an expected String, but deeper dimensions have the same Object.toString() treatment.
  3. Arrays.deepToString(Object[]), while intended for multi-dimensional arrays, produces the expected results for both single and multi-dimensional arrays.
  4. Both Arrays.toString(Object[]) and Arrays.deepToString(Object[]) handle null array gracefully, simply returning a String "null".
I tend to use Java Collections far more than I use Java arrays. However, when I do need to work with arrays, it is nice to have the many useful features of the java.util.Arrays class. As this post has demonstrated, Arrays.toString(Object[]) and Arrays.deepToString(Object[]) are particularly valuable in obtaining a useful String representation of an array's contents. The java.util.Arrays class provides similar "deep" methods for performing equals and hashCode functionality on multi-dimensional arrays: Arrays.deepEquals and Arrays.deepHashCode.

Java's System.identityHashCode

The java.lang.System class provides many useful general utilities including handles to the standard output stream, the standard input stream, the standard error stream, and the console as well as methods for obtaining the current time in milliseconds, defined properties, and environmental variables. In this blog post, I briefly look at the System.identityHashCode(Object) method.

The Javadoc documentation for System.identityHashCode(Object) states:
Returns the same hash code for the given object as would be returned by the default method hashCode(), whether or not the given object's class overrides hashCode().
The System.identityHashCode(Object) method provides the hash code of the provided Object as would be returned from its ultimate Object parent regardless of whether the passed-in object overrode the hashCode method.  This is demonstrated by the following simple class, the source code of which is followed by sample output.

Main.java
package dustin.examples;

import static java.lang.System.out;

public class Main
{
   private static final String NEW_LINE = System.getProperty("line.separator");

   /**
    * Print the overridden and identity hash codes of the provided object.
    *
    * @param object Object whose overridden and identity hash codes are to be
    *    printed to standard output.
    */
   public static void printHashCodes(final Object object)
   {
      out.println(
           NEW_LINE + "====== "
         + String.valueOf(object) + "/"
         + (object != null ? object.getClass().getName() : "null")
         + " ======");
      out.println(
           "Overridden hashCode: "
         + (object != null ? object.hashCode() : "N/A"));
      out.println("Identity   hashCode: " + System.identityHashCode(object));
   }

   /**
    * Main executable function.
    *
    * @param arguments Command-line arguments; none expected.
    */
   public static void main(final String[] arguments)
   {
      final Integer int1 = 1;
      final int int2 = 1;
      final Long long1 = 1L;
      final long long2 = 1L;
      final String str = "SomeString";
      final String nullStr = null;
      final SimpleData simpleData = new SimpleData("AnotherString");

      printHashCodes(int1);
      printHashCodes(int2);
      printHashCodes(long1);
      printHashCodes(long2);
      printHashCodes(str);
      printHashCodes(nullStr);
      printHashCodes(simpleData);
   }
}


Output from Main.java
====== 1/java.lang.Integer ======
Overridden hashCode: 1
Identity   hashCode: 4072869

====== 1/java.lang.Integer ======
Overridden hashCode: 1
Identity   hashCode: 4072869

====== 1/java.lang.Long ======
Overridden hashCode: 1
Identity   hashCode: 1671711

====== 1/java.lang.Long ======
Overridden hashCode: 1
Identity   hashCode: 1671711

====== SomeString/java.lang.String ======
Overridden hashCode: 728471109
Identity   hashCode: 11394033

====== null/null ======
Overridden hashCode: N/A
Identity   hashCode: 0

====== AnotherString/dustin.examples.SimpleData ======
Overridden hashCode: 1641745
Identity   hashCode: 1641745


The example code and its corresponding output indicate that the identity hash code returned by System.identityHashCode(Object) can be different than the object's hash code defined by an overridden version of the hashCode() method. It's also worth noting that if a class does not override hashCode(), then its own hash code will obviously match that provided by Object. In the example above, the SimpleData class (not shown here) does not have a hashCode implementation, so its own hashCode IS the Object-provided hashCode (identity hash code). Another observation that can be made based on the above example is that System.identityHashCode(Object) returns zero when null is passed to it.

Bug 6321873 explains that the hash code returned by System.identityHashCode(Object) is not guaranteed to be unique (it's a hash code after all). That being stated, there are situations in which the hash code returned by System.identityHashCode(Object) is "unique enough" for the problem at hand. For example, Brian Goetz et al. demonstrate use of this to prevent deadlocks in Java Concurrency in Practice.

There are numerous online resources providing greater detail regarding this method. Erik Engbrecht describes how the identity hash code is calculated in his post System.identityHashCode (a topic further discussed in the StackOverflow thread "How does the JVM ensure that System.identityHashCode() will never change?"). Rosarin Roy provides a brief overview of the method in the post System.identityHashCode() - What Is It?

In this blog post, I have looked at a common method that I only use rarely, but which is worth noting for its occasional use. The System.identityHashCode(Object) method is an easy way to obtain the hash code that would have been provided for a particular object if that object's class did not override the hashCode() implementation. The Javadoc documentation for Object.hashCode() tells us that this identity hash code is often, but is not required to be, the memory address of the object converted to an integer.

Tuesday, November 16, 2010

Java 7 and Java 8 JSRs Released!

There has been a lot of big news in the Java world as of late. The recent announcements that IBM is backing OpenJDK and Apple is backing OpenJDK were huge in and of themselves. Today there was more big news with the announcement that Java Specification Requests (JSRs) have been released for Java SE 7, Java SE 8, and related new Java features. The release of these JSRs is the realization of the now famous Plan B announced prior to JavaOne 2010 and then further detailed at JavaOne.

The newly released JSRs (referred to as a JSR Quartet in Mark Reinhold's blog) are JSR 334 ("Small Enhancements to the Java Programming Language") [Project Coin], JSR 335 ("Lambda Expressions for the Java Programming Language") ["informally, closures"], JSR 336 ("Java SE 7 Release Contents"), and JSR 337 ("Java SE 8 Release Contents").

Joseph D. Darcy has provided additional details on the release of JSR 334 (Project Coin) in his blog post Project Coin: JSR Filed! and pelegri likens this quartet of JSRs to the famous quartet known as The Beatles (available on iTunes today). Alex Miller, who has maintained perhaps the most exhaustive collection of what is in and out, back in, and then back out, and then back in, for Java 7, has posted his analysis of the Java 7/Java 8 JSRs.

The release of these four new JSRs indicate that the plans announced for Java prior to and at JavaOne 2010 are moving forward. Coupled with the announced IBM and Apple support of OpenJDK, the future of Java seems very promising.

Saturday, November 13, 2010

Apple and Oracle Are Behind OpenJDK!

I received the November 2010 edition of Oracle's Java Developer Newsletter in my e-mail inbox last night. The lead story is titled IBM Joins OpenJDK (a subject of my previous post IBM and Oracle Are Behind OpenJDK!). On the same day, it was also announced that Apple is joining the OpenJDK effort as well! Henrik Ståhl supplies additional details and answers to likely questions in his post Oracle and Apple Announce OpenJDK Project for OSX. The numerous comments on Henrik's post demonstrate how well this is being received in the Java development community.

Besides the obvious advantage of having power players like Oracle, IBM, and Apple behind OpenJDK, there are other interesting observations to be had here. For one, there had been lots of wailing, gnashing of teeth and complaining about Oracle's heavy-handedness. Similarly, there had been complaints about Apple and its policies and a desire for Apple to provide its OSX implementation as open source. In the end, this happily turns out to be unnecessary angst. Henrik discusses this in his post:
This announcement is the result of a discussion between Oracle and Apple that has been going on for some time. I understand that the uncertainty since Apple's widely circulated "deprecation" of Java has been frustrating, but due to the nature of these things we have neither wanted to or been able to communicate before. That is as it is, I'm afraid.
 I think it's obvious why many of us had concerns about this, but I'm glad that in the end Oracle and Apple were doing what's best for Java.

Another interesting observation or question is what will Google do because or about this? Will Google join the OpenJDK to use in conjunction with Android?

The announcement about Apple joining OpenJDK is huge and positive news for Java developers. I also wonder if some of the many people who talk about Sun as if they could do no wrong and Oracle as if they can do no right will acknowledge that Oracle appears to be doing something with OpenJDK that Sun failed to do: bringing the biggest players in Java together behind a common open source implementation of Java.

Saturday, November 6, 2010

RMOUG Training Days 2011 Schedule-At-A-Glance Available

RMOUG has made the first edition of their Training Days 2011 Schedule-At-A-Glance available online. There are numerous interesting abstracts highlighted in this schedule. My two presentations are both scheduled for the first day and this is unlikely to change because of their respective durations. There is only one 30-minute slot and one 90-minute slot and I have one presentation in each of these slots. The typical RMOUG Training Days presentation slot is 60 minutes. Before highlighting some of the abstracts that look particularly interesting to me, I'll briefly summarize my own presentation abstracts.



Groovier Java Scripting
Session 2 (Wednesday, 16 February 2011, 10:30 am to noon, Room 406)

Groovy is a dynamic language that runs in the Java Virtual Machine and has full access to the Java SDK as well as third-party Java libraries and frameworks. Groovy supports most Java syntax as-is, but provides an even more concise syntax that makes it more suitable for scripting. Groovy can be run directly without explicit compilation and enjoys many other script-friendly benefits.

This presentation expands on topics discussed at RMOUG Training Days 2010 in the presentation "Applied Groovy: Scripting for Java Development." The presentation briefly summarizes select basic features and syntax of Groovy, advantages of using Groovy as a scripting language, and demonstrates how to use Groovy to improve building, developing, and testing Java-based applications. The presentation will emphasize how easy it is to write and parse XML with Groovy and how easy it is to manipulate database content with Groovy.

Although the basics of Groovy will be covered initially in the presentation for those who have not used Groovy previously, most of the syntax and other features covered in this presentation will be presented in conjunction with the use of Groovy in building, maintaining, and testing applications for the Java platform.



Session 4 (Wednesday, 16 February 2011, 2:45 pm to 3:15 pm)

HTML5 is the the forthcoming standard in hypertext markup for the modern web. Although work on HTML5 has been ongoing for several years, interest and support for HTML5 has increased rapidly in recent months. An example of this is the JavaOne 2010 announcement that JavaFX 2.0 will provide HTML5 support. This short presentation will describe some of the most exciting features of HTML5. The presentation also covers the reasons that HTML5 is important and describes some of its limitations and obstacles to adoption. Finally, HTML5 features already supported in three popular modern web browsers (Microsoft Internet Explorer, Firefox, and Google Chrome) will be demonstrated.




There are numerous other abstracts that appeal to my interests. I probably won't attend the Tuesday University Sessions, but Brad Brown's Building Enterprise Apps for the Android Platform looks interesting. In his abstract, Brown states something that I've felt and been telling people as well:
I liken Android to the 'IBM PC' of the mobile world. Apple came out with a great OS for the Mac, but it only ran on the Mac. The 'IBM PC' (DOS, which later became Microsoft Windows) was generic and ran on a variety of hardware. Android runs on hundreds of devices today.
Brown's abstract states that this University Session will "discuss how you can write an application for the Android that accesses your corporate data securely. From concept to publishing in the Android market - for sale or for free - private or public."

One disadvantage of my presenting A First Look at HTML5 in the 30-minute Quick Tip presentation slot is that I won't be able to attend Rob Osterburg's presentation Scala: A Concise Introduction through Code, Concepts and Demonstrations. I'm not normally in the habit of recommending attendees attend a presentation at the same time as mine, but I would have liked to attend this session because Rob is a friend and because the topic (Scala) is of significant interest to me. In fact, attendees at my Groovy presentation will likely hear me enthusiastically recommend his session on another JVM-based programming language.

Gwen Shapira (blog) has an abstract discussing another topic of high interest to me: NoSQL (see my coverage of a JavaOne 2010 presentation on NoSQL). Her presentation is called NoSQL Deep Dive and her abstract summarizes NoSQL: "NoSQL is a general name for a new type of database - One that throws away the relational model in favor of better scalability."

Another abstract title that stood out to me as I scanned the Schedule-At-A-Glance is Introduction to Mobile Application Development. This abstract states that the presentation will "cover introduction, approach, and leading practices for building applications in a mobile platform" and will provide an iPhone example.

The Rocky Mountain Oracle Users Group is deeply rooted in Oracle database technology and this year's slate of presentations, like most years before, provides numerous in-depth database-heavy topics. Similarly, it is not surprising that many Oracle tools received focused coverage in RMOUG Training Days 2011 presentations. The schedule is subject to change (one presentation still needs a title!), but it is interesting to start planning what I will attend.

RMOUG Training Days 2011 will be held February 15-17, 2011 (15 February is University Sessions) at the Colorado Convention Center in Denver, Colorado. The Colorado Convention Center has a Flash-based interactive floor map available for seeing where the rooms for each session are located.

Monday, November 1, 2010

Highlights of RMOUG SQL>Update Fall 2010 Newsletter

I received a copy of the Fall 2010 edition of the Rocky Mountain Oracle Users Group newsletter (RMOUG SQL>Update) this week and summarize some of its highlights here. The cover of this edition is perfect for a Fall/Autumn edition and features a photograph (by Lisa Collett) of aspen trees whose leaves have already turned yellow.

This edition of the RMOUG newsletter has several references to Training Days 2011. In her "From the President" column, RMOUG President Peggy King writes about the upcoming RMOUG Training Days 2011 and mentions that this conference will be held February 15-17, 2011, at the Colorado Convention Center. She states that there was an "overwhelming response to this year's call for papers" that "promises to continue the long standing RMOUG tradition of providing a conference packed full of exceptional presentations and numerous opportunities to share knowledge and hear the latest information about product development."  She adds, "So look for the Training Days 2011 Preliminary Conference agenda to be posted to the RMOUG website (www.rmoug.org) around the middle of November." Peggy states (and some advertisements in the newsletter reaffirm) that early registration for RMOUG Training Days 2011 will be available in early November.

RMOUG Training Days 2011 is also mentioned in Brad Blake's summary of Oracle OpenWorld 2010. He compares Oracle OpenWorld and RMOUG Training Days and concludes that RMOUG Training Days "is always a much better 'bang for the buck'!" in terms of providing "good, technical session[s]" that provide "actual hands-on tips and tricks of how to do things -- something you can take back to the office and USE."

There is more than one advertisement for Training Days 2011 in this edition, but the largest and most obvious is on the back cover. This advertisement includes the dates (15-17 February 2011) and the location (Colorado Convention Center in Denver, Colorado) and states that early registration will open November 4, 2010, and that early registration ends January 12, 2011.

RMOUG Training Days 2011 is not the only RMOUG training-related event coming up in the relatively near future. Page 5 of this Fall 2010 newsletter has an advertisement for the Fall Quarterly Education Workshop to be held on 19 November 2010. The advertisement on page 31 talks about the "next Quarterly Education Workshop in August at the Regis Science Ampitheatre," but it appears to me that that website should be checked for confirmation on the location.

In "MR Trace: An Interview with Cary Millsap of Method R," Cary Millsap answers a set of questions about Method R's offerings. Millsap talks about Method R Trace, a platform-independent Java-based extension of Oracle SQL Developer. Millsap describes this product's "purpose in life": "to completely eliminate all of the distractions associated with getting your hands on perfectly scoped Oracle extended SQL trace data." Millsap goes onto say that Method R Trace is designed for and targeted at software developers. He also references a 3-minute YouTube video on using this product and references his blog post on MR Trace's new file delete function. Finally, Millsap introduces "the best-kept secret in our company": MR Tools Suite. This suite includes three tools: mrls, mrnl, and mrskew. This article was unquestionably heavy on marketing and sales, but I did find it interesting that MR Trace is developer-focused and the tools do sound useful.

This edition of the newsletter continued two series of articles that began in the Summer 2010 edition of the newsletter. Jed Walker's "Quick Guide to Configuring Oracle 11gR2 Data Guard Physical Standby" had Part 2 covered in this Fall 2010 edition after having Part 1 covered in the Summer 2010 edition. Similarly, Dan Hotka continued his "Oracle Trace Facility" series: the Summer 2010 edition (Part I) focused on TOAD Trace File Analysis and the Fall 2010 edition (Part II) focused on Metalink SQL T (SQLTXPLAIN).

Other technical articles in the Summer 2010 edition of the RMOUG newsletter were Rama Balaji's "Flashback Logs Cleanup Without Downtime" and Kellyn Pedersen's "The CTAS, a.k.a. Processing Data The Jetson's Way." The other technical articles in the Fall 2010 edition of SQL>Update included Sue Harper's "Capture, Model, Design and Generate Using Oracle SQL Developer Data Modeler."

The Fall 2010 edition of the RMOUG newsletter had its "RMOUG Board Focus" focused on Tim Gorman. His column is an interesting case study in how what's important is in the eye of the beholder and how we all seem to think whatever we do is most important. I have a difficult time arguing with him that data is extremely valuable. I'm just glad we all can find things we enjoy that are different so we're not all trying to do the same thing. I don't think I could be a DBA for more than a few days without the desperate need to throw myself off the tallest building I could find, but he probably feels similarly about software development. It's good that we don't all want to do the same job. I'm not arguing that data's not valuable; it's just not that interesting!

As I stated previously, the Fall 2010 edition had numerous references to RMOUG Training Days 2011 and the Preliminary Agenda is expected to be available in November.  Ken Lee has announced that his abstract has been accepted for "APEX-O-MATIC – In a Blender with APEX and Web Services."

I was excited to learn this week that the two abstracts I submitted have been accepted. I will be presenting "Groovier Java Scripting" and "A First Look at HTML5." The Groovy presentation will expand on what I presented last year at Training Days 2010 ("Applied Groovy: Scripting for Java Development") on Groovy and provide more concrete examples of scripting with Groovy. The HTML5 presentation will look at what HTML5 offers in several browsers already and promises to offer for future web development. I plan to post the actual abstracts and additional details about my plans for these two presentations in a future post.