Overview of the op4j library

I’m a huge Groovy fan. Still in process of learning it but already understand that some of its features are really outstanding. I wish we have the same collections and closure support in plain Java. However it will take some time until Java 7/8 would be released to use all these tasty things in production. Found out that there’s a nice library which can make a day-to-day development easier. It’s called op4j. Used the latest version 1.1 in this small overview.

So this overview consists of the following parts:

  1. Scenarios
  2. Functions Overview
  3. Conclusion


Scenarios
This section describes usual scenarios where op4j can be useful.

1. Conversion between various collection types: arrays, lists. maps, sets, tuples


String[] values = new String[]{"q1", "w2"};
List<String> list = Op.on(values).toList();

As a result of this code you’ll get a list of values from the array.

2. Transformation of the arrays, collections and maps

String[] values = new String[]{"q1", "w2"};
List<String> upperStrs = Op.on(values).toList().map(FnString.toUpperCase()).get();
// upperStrs = ["Q1", "W1"]

As a result of this code you’ll get a list with the transformed values.

3. Creating functions dynamically and passing them through the methods like for Closures in Groovy

Function<String[],List<String>> upperStrsFunc =
Fn.onArrayOf(Types.STRING).map(FnString.toUpperCase()).toList().get();

As a result the function which transforms array to the list of the uppercase items is created and you can later pass this function somewhere and execute.

List<String> upperStrs = upperStrsFunc.execute(new String[]{"q1", "w2"});
// upperStrs = ["Q1", "W1"]

4. Quick building list from the values(useful in the unit tests)

List<String> items = Op.onArrayFor("hello", "ola", "hola", "hallo", "ciao").toList().get()
// items = {"hello", "ola", "hola", "hallo", "ciao"}

Map<Integer, String> map = Op.onArrayFor(1,2).zipValues("a","b").get();
// map = {1:"a", 2: "b"}

5. Grouping some data

Map<Integer, String[]> mapOfArrays =
Op.onArrayFor(1,2,1,2,2).zipAndGroupValues(Types.STRING, "a","b","c","d","e").get();
// mapOfArrays = {1:["a","c"], 2: ["b","d","e]}

As a result the data is grouped by the first array

6. Modifying collections

String[] data = Op.on(new String[]{"hello", "ola", "hola", "hallo", "ciao"}).add("test").get()
// data = ["hello", "ola", "hola", "hallo", "ciao", "test"]

For example you can easily add data into array.

String[] data = Op.on(new String[]{"hello", "ola", "hola", "hallo", "ciao"}).removeAllTrue(new IFunction<String, Boolean>() {
@Override
public Boolean execute(String arg0, ExecCtx arg1) throws Exception {
return arg0.contains("llo");
}}.get();
// data = ["ola", "hola", "ciao"]

Also you can remove data based on some condition

7. Filtering data

String[] data = Op.on(new String[]{"hello", "ola", "hola", "hallo", "ciao"}).forEach().ifIndex(1, 3).get();
// data = ["ola", "hola"]

As a result the resulting array has filtered values

8. Removing duplicates

String[] data = Op.on(new String[]{"hello", "ola", "hello", "hallo", "hello"}).distinct().get();
// data = ["hello", "ola", "hallo"]

As a result – no duplicates in the array.

Functions Overview

Functions play a major role in op4j and they are vitally important when working with different kinds of data sets. So lets have a quick overview of those available and note the most interesting from my point of view.

1. Call. It’s not a function itself but a sort of wrapper around reflection.

List<User> users = ...;
Group group = ...;
...
List<User> usersInGroup =
Op.on(users).removeAllFalse(Call.bool("isInGroup", group).get();

This code removes all users which are not in the specific group by calling isInGroup method on every user.

2. FnFunc. Contains functionality for chaining and conditions. The most interesting methods are:

  • chain – chains several functions.
  • if[False|True|Null|NotNull][And[False|True|Null|NotNull]]?Then[Else]? – provides various types of the conditional function execution.

3. FnBoolean. Various kinds of boolean functions. 4. FnCalendar / FnDate. Various kinds of calendar/date functions. The most interesting methods are:

  • fieldStringArrayToCalendar – constructs a date from the string array.
  • toStr – formats a date based on the passed date format.

5. FnString. Wraps usual methods provided by String calls but also adds incredibly valuable methods like:

  • escape[CSV|HTML|XML|JavaScript] – escaping strings.
  • unescape[CSV|HTML|XML|JavaScript] – unescaping strings.
  • isBlank – the same as StringUtils.isBlank from commons-lang.
  • joinArray – joins array of values into a single string. A similar method is available in commons-lang also.

6. FnNumber/FnBigDecimal/FnBigInteger/FnInteger/FnLong/FnFloat/FnDouble/FnShort. Various kinds of number functions

Conclusion
This library brings lots of flexible API to work with the different kinds of collections and process them in the closure manner. Now it’s in my list of the musthave libraries for the Java projects along with commons-lang and commons-logging.