Sunday, October 08, 2017

Java 9: My favourite feature!

First of all, sorry about the "click-baity" title!

My favourite feature in Java 9 has to be the Javadoc Search.

The Java API documentation now has a search box which you can use to find packages, types and methods quickly. It would be nice if it supported regular expressions :)

Here is a screencast GIF showing the Javadoc Search in action, created using LICECap:

Saturday, October 07, 2017

Using XSLT 2.0 with Java and Saxon

In my previous post, I showed how you can split a string using the tokenize function in XSLT 2.0. In order to run an XSLT 2.0 stylesheet in Java, you need a transformer that supports XSLT 2.0. Unfortunately, the default JAXP transformer (com.sun.org.apache.xalan.internal.xsltc.trax.TransformerImpl) does not. Instead, use Saxon, which supports both XSLT 2.0 and 3.0.

The class below shows how you can perform an XSL transformation in Java, using Saxon and the JAXP interface:

import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

public class XSLTransformer {

  private final Templates templates;

  public XSLTransformer(final String xslFileName) throws Exception {
    templates = new net.sf.saxon.BasicTransformerFactory().newTemplates(
        new StreamSource(XSLTransformer.class.getClassLoader()
                             .getResourceAsStream(xslFileName)));
  }

  public String transform(final String xml) throws Exception {
    final Transformer transformer = templates.newTransformer();
    final StringWriter writer = new StringWriter();
    transformer.transform(new StreamSource(new StringReader(xml)),
                          new StreamResult(writer));
    return writer.toString();
  }
}

An alternative to the JAXP interface is to use Saxon's own s9api interface, which is more robust:

import java.io.StringReader;
import java.io.StringWriter;

import javax.xml.transform.stream.StreamSource;

import net.sf.saxon.s9api.Processor;
import net.sf.saxon.s9api.SaxonApiException;
import net.sf.saxon.s9api.XsltExecutable;
import net.sf.saxon.s9api.XsltTransformer;

public class SaxonTransformer {

  private final Processor processor;
  private final XsltExecutable xsltExec;

  public SaxonTransformer(final String xslFileName) throws SaxonApiException {
    processor = new Processor(false);
    xsltExec = processor.newXsltCompiler().compile(new StreamSource(
        XSLTransformer.class.getClassLoader().getResourceAsStream(xslFileName)));
  }

  public String transform(final String xml) throws Exception {
    final XsltTransformer transformer = xsltExec.load();
    transformer.setSource(new StreamSource(new StringReader(xml)));
    final StringWriter writer = new StringWriter();
    transformer.setDestination(processor.newSerializer(writer));
    transformer.transform();
    return writer.toString();
  }
}

Splitting a string using XSLT 2.0

The tokenize function available in XSL Transformations (XSLT) Version 2.0 allows you to split a string on any separator that matches a given regular expression.

The example below shows how you can split a comma-delimited string:

Input XML:

<data>
  <stringToSplit>foo,bar,baz</stringToSplit>
</data>

XSL 2.0 Stylesheet:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="data">
    <items>
      <xsl:variable name="stringToSplit" select="stringToSplit" />
      <xsl:for-each select="tokenize($stringToSplit, ',')">
        <item>
          <xsl:value-of select="." />
        </item>
      </xsl:for-each>
    </items>
  </xsl:template>
</xsl:stylesheet>

Output XML:

<?xml version="1.0" encoding="UTF-8"?>
<items>
  <item>foo</item>
  <item>bar</item>
  <item>baz</item>
</items>

Sunday, October 01, 2017

Java 9: Creating Immutable Collections

Static factory methods have been added in JDK 9, to allow you to easily create immutable lists, sets and maps.

Immutable Lists

Use the List.of() static factory methods to create immutable lists.

// in JDK 9
List<String> list = List.of("foo", "bar");

// in JDK 8
List<String> list2 = Collections.unmodifiableList(Arrays.asList("foo", "bar"));

// in Guava
List<String> list3 = ImmutableList.of("foo", "bar");

Immutable Sets

Use the Set.of() static factory methods to create immutable sets.

// in JDK 9
Set<String> set = Set.of("foo", "bar");

// in JDK 8
Set<String> set2 = Collections.unmodifiableSet(
                       new HashSet<>(Arrays.asList("foo", "bar")));

// in Guava
Set<String> set3 = ImmutableSet.of("foo", "bar");

Immutable Maps

Use the Map.of() and Map.ofEntries() static factory methods to create immutable maps.

// in JDK 9
Map<String, Integer> map = Map.of("key1", 1, "key2", 2);
// for more than 10 key-value pairs, use Map.ofEntries
Map<String, Integer> map2 = Map.ofEntries(entry("key1", 1),
                                          entry("key2", 2));

// in JDK 8
Map<String, Integer> map3 = new HashMap<>();
map3.put("key1", 1);
map3.put("key2", 2);
map3 = Collections.unmodifiableMap(map3);

// in Guava
Map<String, Integer> map4 = ImmutableMap.of("key1", 1, "key2", 2);
// or, for more than 5 key-value pairs:
Map<String, Integer> map5 = ImmutableMap.<String, Integer>builder()
                                .put("key1", 1)
                                .put("key2", 2)
                                .build();

Implementation Details

It's interesting to look at the implementation of these static factory methods. They return a different class based on which method you use e.g. if you call List.of(e1) you get an instance of ImmutableCollections.List1 but if you call List.of(e1, e2) you get an instance of ImmutableCollections.List2. These are compact field-based classes that consume less heap space than their unmodifiable (or mutable) equivalents.

Note that the immutable collections returned by the static factory methods are not "wrapper" collections like those returned by Collections.unmodifiable. With an unmodifiable collection, you can still modify the underlying collection if you have a reference to it, but an immutable collection will always throw an exception if you try to modify it.

Java 9: Eclipse Installation

Java 9 is out! This post shows you how to get developing with Java 9 in Eclipse straightaway!

  1. Install JDK 9
  2. Install Eclipse Oxygen
  3. Install Java 9 Support for Oxygen in Eclipse
  4. Finally, go to "Window > Preferences > Java > Installed JREs" in Eclipse and add your Java 9 JRE

That's it!

Update (14-Oct-2017): Eclipse Oxygen.1a (4.7.1a) supports Java 9, so the "Java 9 Support for Oxygen" plugin is no longer required.

Sunday, August 27, 2017

Java: Enforcing a minimum number of method arguments using varargs

Sometimes you need to write a method that requires at least a certain number of arguments. For example, let's say you have a calculation that requires three or more integer arguments. You could write it like this:

public static int calculate(int... args) {
  if (args.length < 3) {
    throw new IllegalArgumentException("At least 3 arguments expected");
  }
  // do something
  return result;
}

The problem with this is that the client cannot tell how many arguments are required and, if they are pass in too few arguments, the method will fail at runtime rather than compile time. You also have to explicity validate the number of arguments passed into the method.

A better way is to declare the method to take 3 normal arguments and 1 varargs arguments, like this:

public static int calculate(int a, int b, int c, int... rest) {
  // do something
  return result;
}

Saturday, July 29, 2017

Java 8: Multimaps

A multimap is a Map which maps a single key to multiple values e.g. HashMap<String, List<String>>.

Java 8 introduces a Map.computeIfAbsent method, which makes inserting values into a multimap much simpler:

Map<String, List<String>> multimap = new HashMap<>();
multimap.computeIfAbsent(key, k -> new ArrayList<>()).add(value);

Prior to Java 8, a multimap was usually created as follows:

// create the map
Map<String, List<String>> multimap = new HashMap<>();

// put a key/value into the map
List<String> list = multimap.get(key);
if (list == null) {
  multimap.put(key, list = new ArrayList<>());
}
list.add(value);

Or with Guava's Multimap class:

ListMultimap<String, String> multimap = ArrayListMultimap.create();
multimap.put(key, value);

You can read more about Java 8 updates to the Map class in my previous blog post.

Saturday, July 22, 2017

Java: Splitting a Pipe-delimited String - Fast!

This post shows how you can efficiently split a pipe-delimited string e.g. "foo|bar|baz". There are many ways to do this - I could even write my own - but I will only use those that are available in the JDK (or commonly used libraries) and will measure the performance of each.

Remember that, since the pipe symbol (|) is a special character in regular expressions, it needs to be escaped if necessary.

1. String.split

The most obvious way to split a string on the pipe character is to use Java's String.split:

public static String[] split(String s) {
  return s.split("\\|");
}

2. String.split with Pattern.quote

Instead of escaping the pipe ourselves, we can use Pattern.quote to do it for us. (Note: Pattern.quote("|") returns "\Q|\E".)

public static String[] splitWithPatternQuote(String s) {
  return s.split(Pattern.quote("|"));
}

3. Pattern.split

Create a static Pattern and use it to split the string.

private static final Pattern SPLITTER = Pattern.compile("\\|");

public static String[] splitWithPattern(String s) {
  return SPLITTER.split(s);
}

4. StringUtils.split

Apache Commons provides StringUtils.split, which splits a string on a single character:

import org.apache.commons.lang3.StringUtils;

public static String[] splitWithStringUtils(String s) {
  return StringUtils.split(s, '|');
}

So, which one is fastest?

I ran each method on 1 million pipe-delimited strings of different lengths - RandomStringUtils.randomAlphabetic is great for generating random strings - and the table below shows how long each one took:

MethodTime (ms)
split485
splitWithStringUtils520
splitWithPattern643
splitWithPatternQuote936

An interesting observation is that splitWithPatternQuote is so much slower than split, even though they both call String.split internally! If we delve into the source code for String.split, we can see that there is an optimisation (a "fastpath") if the provided regex has two-chars and the first char is a backslash. This applies to "\\|" but, since Pattern.quote produces \Q|\E, it does not use the fastpath and instead creates a new Pattern object for every split. This also explains why it is slower than splitWithPattern, which re-uses the same Pattern object.

Monday, May 29, 2017

Stack Overflow - 150,000 rep reached!

I've been a bit quiet on Stack Overflow lately, but just managed to reach 150,000 reputation!

For me, Stack Overflow has not simply been a quest for reputation, but more about learning and helping fellow programmers in need.

Sunday, May 21, 2017

Shell Scripting: <, << and <<<

This post shows the difference between the three standard input redirection operators: <, << and <<<.

1. <

< allows you to pass data contained in a file to the standard input of a command. The format is:

command < file

Examples:

# replace comma with new-lines:
tr ',' '\n' < file

# read a file line-by-line and do something with each line:
while IFS= read -r line; do
  # do something with each line
  ssh "$line" who -b
done < hosts.txt

2. <<

<< allows you to pass multi-line text (called a here-document) to a command until a specific "token" word is reached. The format is:

command << TOKEN
line 1
line 2
TOKEN

For example:

# query a database
sqsh -S server -D db << END
select * from table
where foo='bar'
go
END

3. <<<

<<< allows you to pass a string of text (called a here-string) to a command. If you find yourself echo-ing text and piping it to a command, you should use a here-string instead. (See my previous post on Useless Use of Echo.) The format is:

command <<< text

Examples:

tr ',' '\n' <<< "foo,bar,baz"

grep "foo" <<< "foo,bar,baz"

mailx -s subject $USER <<< "email body"

Saturday, March 11, 2017

Java 8: Tree Traversal Using Streams

It's quite common to traverse a tree using recursion, but with Java 8 it is now possible to lazily traverse a tree using streams.

The class below represents a tree. The stream() method streams the nodes contained in the tree. You can then do all the cool things that you can do with other streams, such as filtering, mapping and collecting!

public class TreeNode<E> {

  private final E data;
  private final List<TreeNode<E>> children;

  /**
   * Creates the tree node with the specified data and no children.
   * @param data
   */
  public TreeNode(final E data) {
    this.data = data;
    this.children = new ArrayList<>();
  }

  /**
   * @return the data contained in this node
   */
  public E getData() {
    return data;
  }

  /**
   * Adds a child to this tree node.
   * @param data the data to add
   */
  public TreeNode<E> addChild(final E data) {
    final TreeNode<E> toAdd = new TreeNode<>(data);
    children.add(toAdd);
    return toAdd;
  }

  /**
   * @return a stream of nodes in this tree in depth first order
   */
  public Stream<TreeNode<E>> stream() {
    return Stream.concat(Stream.of(this), children.stream().flatMap(TreeNode::stream));
  }
}

Example usage:

TreeNode<String> root = new TreeNode<>("Root");
TreeNode<String> a = root.addChild("A");
a.addChild("A1");
a.addChild("A2");
root.addChild("B");
TreeNode<String> c = root.addChild("C");
c.addChild("C1");

int count = root.stream().count(); // 7

String tree = root.stream().map(TreeNode::getData).collect(Collectors.joining(","));
// Root,A,A1,A2,B,C,C1

Saturday, January 28, 2017

Power Set Algorithm - Iterative

The power set of a set S is the set of all subsets of S including the empty set and S itself. For example, the power set of {1, 2, 3} is {{}, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1, 2, 3}}.

Previously, I wrote about how you can generate the power set using a recursive algorithm. This time I'll show you how to use iteration.

Recall, that when we are generating a set for the power set, each element can either be in the set or out of the set. In other words, each set can be represented in binary form, where 1 means that the element is in the set and 0 means that it is not. For example, given a set {a, b, c}, the binary string 101 would represent {a, c}.

Generating the power set just comes down to generating all numbers from 0 to 2^n (since there are 2^n possible subsets) and converting the binary representation of the number into the set!

Here is the algorithm:

public static <E> List<List<E>> powerSet(final List<E> list) {
  final List<List<E>> result = new ArrayList<>();
  final int numSubSets = 1 << list.size(); // 2^n
  for (int i = 0; i < numSubSets; i++) {
    final List<E> subSet = new ArrayList<>();
    int index = 0;
    for (int j = i; j > 0; j >>= 1) { // keep shifting right
      if ((j & 1) == 1) { // check last bit
        subSet.add(list.get(index));
      }
      index++;
    }
    result.add(subSet);
  }
  return result;
}

Sunday, January 22, 2017

Java 8: Top N elements from a stream

This post shows how you can sort a stream in reverse order and then select the top N elements.

This is quite common in financial systems.

For example, let's say that you have a list of currency exchange rate movements and you want to see the top 5 largest movements. You can do this using Java 8 Streams as shown below:

import static java.util.Comparator.*;
import static java.util.stream.Collectors.*;

// list of currency exchange rate percentage moves
final List<Currency> currencies = Arrays.asList(
    new Currency("EUR/USD", 0.37),
    new Currency("USD/JPY", -0.21),
    new Currency("GBP/USD", 0.27),
    new Currency("AUD/USD", -0.08),
    new Currency("USD/CAD", 0.02),
    new Currency("USD/CHF", -0.46),
    new Currency("EUR/JPY", 0.16),
    new Currency("EUR/GBP", 0.13),
    new Currency("USD/HKD", 0.0),
    new Currency("EUR/CHF", 0.05),
    new Currency("USD/KRW", -0.71)
    );

currencies.stream()
  .sorted(comparing(Currency::getMove, comparing(Math::abs)).reversed())
  .limit(5)
  .collect(toList());

The result is:

Currency [ccy=USD/KRW, move=-0.71]
Currency [ccy=USD/CHF, move=-0.46]
Currency [ccy=EUR/USD, move=0.37]
Currency [ccy=GBP/USD, move=0.27]
Currency [ccy=USD/JPY, move=-0.21]

The two argument Comparator.comparing method easily allows us to compare currency moves on absolute value.

Sunday, January 01, 2017

fahd.blog in 2016

Happy 2017, everyone!

I'd like to wish everyone a great start to an even greater new year!

In keeping with tradition, here's one last look back at fahd.blog in 2016.

During 2016, I posted 20 new entries on fahd.blog. I am also thrilled that I have more readers from all over the world! Thanks for reading and especially for giving feedback.

Top 5 posts of 2016:

I'm going to be writing a lot more this year, so stay tuned for more great techie tips, tricks and hacks! :)

Related posts: