Java 9 : Collections factory methods

As of Java 8, there’s  no simple or single statement way of creating collections with a small number of elements. In scenarios like unit tests where a Set of Strings are to be created as mock data,  it is needed to create a new Set and start repeatedly adding the elements which is highly verbose. Java 9 simplifies it through varargs based factory methods to create collections with a small number of elements. List, Set and Map interfaces have of method that creates the respective immutable Collection/Map. These convenience methods are implemented based on varargs

Creating a List

Prior to Java 9, immutable list is created using

List<String> immutableList = Arrays.asList("Cersei", "Hound", "Ilyn Payne", "Melissandre", "Beric Dondarrion");

if we add an element to the immutableList,

immutableList.add("Walder Frey");

an UnsupportedOperationException is thrown. This is OK as we expect the list to be immutable. But the List returned by Arrays.asList is vulnerable to set operation

immutableList.set(2, "Walder Frey");

after this operation, Ilyn Payne is replaced by Walder Frey.

in Java 9 an immutable list can be created using

List<String> immuatbleListJ9 = List.of("Cersei", "Hound", "Ilyn Payne", "Melissandre", "Beric Dondarrion");

if we add an element to the immutableListJ9

immutableListJ9.add("Walder Frey");

an UnsupportedOperationException is thrown as expected.

if we try set operation

immutableListJ9.set(2, "Walder Frey");

an UnsupportedOperationExceptionon is thrown.

Creating a Set

Prior to Java 9, there’s no easy way to create a Set
One way is to create a new Set and add elements one by one

Set<String> theSet = new HashSet&lt;&gt;();
theSet.add("Cersei");
theSet.add("Hound");
theSet.add("Ilyn Payne");

other way is to use

Set<String> theSet = new HashSet<>(Arrays.asList("Cersei", "Hound", "Ilyn Payne", "Melissandre", "Beric Dondarrion")); 

The Set created in above ways is mutable, we can keep adding or removing elements to or from it. This Set can be converted to immutable with the help of Collections.unmodifiableSet

in Java 9, the Set can be created using

Set<String> theSetJ9 = Set.of("Cersei", "Hound", "Ilyn Payne", "Melissandre", "Beric Dondarrion");

The Set created using factory method is an immutable set, it con’t be modified. If try to add or remove an element to or from this set, an UnsupportedOperationException is thrown.

Creating a Map

Prior to Java 9, Map also doesn’t have a easy way to create

Map<Integer, String> theMap = new HashMap&gt;();
theMap.put(1, "Cersei");
theMap.put(2, "Hound");
theMap.put(3, "Ilyn Payne");

The Map created in above way is mutable, we can keep adding or removing entries to or from it. This map can be converted to immutable with the help of Collections.unmodifiableMap

in Java 9, the Map can be created using

Map<Integer, String> theMapJ9 = Map.of(1, "Cersei", 2, "Hound", 3, "Ilyn Payne", 4, "Melissandre",
5, "Beric Dondarrion");

Map.of() method expects the arguments in key1, value, key2, value2 …. keyn, valuen order. As the map needs two different types of elements, Map.of method doesn’t take varags instead it has over loaded versions that takes upto 10 key-value pairs. Map has another version that takes the varags of Map.Entry<K,V>; Map.ofEntries(Map.Entry<K,V> ....). To facilitate the easy creation of Map.Entry objects, another convenience method, Map.entry() is added to the Map interface. Using these two convenience methods a Map object can be created

Map<Integer, String> theMapJ9 = Map.ofEntries(entry(1, "Cersei"), entry(2, "Hound"), entry(3, "Ilyn Payne"),
entry(4, "Melissandre"), entry(5, "Beric Dondarrion")); 

If we perform a put operation on this map, an UnsupportedOperationException is thrown.

The convenience factory methods of List, Set and Map interfaces provides an easy way to create an instance of respective Collection or Map with a small number of elements. The Objects returned by these methods are immutable, any operation trying to modify them will throw an UnsupportedOperationException.

Different ways of String formatting in Java : Benchmarking

Java programmers use mostly the following three ways for formatting or building a string.

  1. String concatenation using + operator
  2. Using String.format
  3. Using StringBuilder

Functionally all these 3 ways will produce the same result but the question is “are all the 3 ways have the same time and space performance?“. I wrote small code snippet to benchmark these three ways.

public static long  stringConcat(int iterations) throws InterruptedException {
		String cersei = "Cersei";
		String nightKing = "Night King";
		long startTime = System.currentTimeMillis();
		for(int i=0; i&lt;iterations; i++) {
		 if(i%2 == 0) {
			String s = i+" Who"+" will"+" kill " + cersei;
		 } else {
			 String s = i+" Is"+ " it " + nightKing;
		 }
		}
		long endTime = System.currentTimeMillis();
		return endTime-startTime;
	}

	public static long stringFormat(int iterations) {
		String cersei = "Cersei";
		String nightKing = "Night King";
		long startTime = System.currentTimeMillis();
		for(int i=0; i&lt;iterations; i++) {
		 if(i%2 == 0) {
			String s = String.format("%d %s %s %s %s", i, "who", "will", "kill", cersei);
		 } else {
			 String s = String.format("%d %s %s %s", i,"is",  "it",  nightKing);
		 }

		}
		long endTime = System.currentTimeMillis();
		return endTime-startTime;
	}

	public static long stringBuilder(int iterations) {
		String cersei = "Cersei";
		String nightKing = "Night King";
		long startTime = System.currentTimeMillis();
		for(int i=0; i&lt;iterations; i++) {
		 if(i%2 == 0) {
			StringBuilder sb = new StringBuilder();
			sb.append(i).append(" who").append(" will").append(" kill ").append(cersei);
			String s = sb.toString();
		 } else {
			 StringBuilder sb = new StringBuilder();
				sb.append(i).append("Is").append(" it").append(nightKing);
				String s = sb.toString();
		 }

		}
		long endTime = System.currentTimeMillis();
		return endTime-startTime;
	}

Ran all 3 methods with an iteration count of 100000.

  1. String concatenation took ~110ms
  2. String.format took ~1600ms
  3. StringBuilder took ~80ms

String.format takes considerably more time because it internally uses the java.util.Formatter and creates several instances of Formatter and other utility Objects that consumes the considerable amount of CPU time and memory. Below is the screen shot of the profiling for this case. We can see that there lot of additional objects being created.

STringFormatProfile.jpg

Similarly I profiled the other methods as well and observed that String concatenation creates more objects than the StringBuilder.

In summary,

String concatenation and StringBuilder performs almost equal w.r.t time complexity but the StringBuilder performs better in terms of space complexity. If performance is a concern, never use String.format.  

 

 

Handling unused imports in Eclipse

The following three ways can be used to fix the unused imports in Eclipse

  1. If you have a file or two with unused imports, open the file that has unused imports and use ctrl+shift+O, this automatically organizes the imports; removes unused and adds any missing imports
  2. Avoid unused imports by enabling the organize imports option in Window -> Preferences -> Java -> Editor -> Save Actions . Once this is done eclipse removes the imports automatically when a file is savedUnusedImport_SaveAction.jpg
  3. When there are already a large number of unused imports, all of them can be fixed at once by following the below steps
  • Open the Problems window in eclipse, select all the unused imports warnings
  • Right click on them and select the Quick Fix optionImport_QuickFix.jpg
  • Above step opens Quick Fix pop-window, click finishUnusedImport_SaveAction.jpg

 

JShell : A Primer


JShell is the REPL (Read-Eval-Print Loop) for java introduced as part of JDK 9. It is an interactive command line interface that enables the users to execute a single statement at a time, JShell evaluates and prints the result of the statement. The statement can be any valid java statement ranging from declaration of a variable to a basic arithmetic operation ….. to defining a class.

JShell is a handy tool for the language learners  and for experienced java programmers as well to try out something quickly. We all know the pain we went through when we started learning Java; to run a simple System.out.println, we had to create a Class with main method, compile it and run it. Even the worse when we want to do it in IDE, have to create a Project, then package and class. It’s a kind of turn off for someone who’s experienced in Scala or Python and trying to learn Java. Now with the JShell, it’s a more seamless learning experience for beginners of the Java, you are not obligated to create a class and a main method and even liberated from the semicolon at the end of every statement.

JShell can be found in bin directory of the JDK installation, can be launched from the command line interface of the operating system. I have used the windows 10. Below screen shot shows the command to launch JShell.

launch.jpg
Launch JShell

What can we do with JShell

  1. Perform simple arithmetic operations such as 1+2 or 5%2, Jshell evaluates and prints the resultarithmetic.jpg
  2. Print a string or any value by directly typing System.out.print. We can declare a variable and then we can print it. The below image shows printing of String directly typed in System.out.print and declaring a starting variable and then printing it. Once a variable is declared, JShell prints the variable name and value PrintString.jpg
  3. Execute a loop statement, print values from 0 to 9 using for looploop.jpg
  4. Declare a method and call that method. In the example shown in the image, I have declared a method printString that takes a String argument and prints it, then I called that method with the String value “Calling a method from JShell”; the method is executed and the string value is printed on the console. Method.jpgif we type any semantically wrong code, an error is shown. I have tried inserting an extra double quote inside the println after the variable name and I saw the error as belowFunctionError.jpg
  5. View the history of the statements executed with /list command.list.jpg
  6. View the variables and the methods declared with /v and /m commandsVariablesNMethods.jpg$1 is the variable that is created as a result of the arithmetic operation 1+2. When user performs an operation without assigning the result to a variable, JShell creates a variable automatically, $1 and $2 are such variables and str is the variable for the String literal created.
  7. JShell evaluates the method dependencies,  shows a warning if a method definition is not found. If we declare a method, method1 and if it calls an undefined method, method2, JShell shows warning as shown in the image belowmethod_dep.jpgif we list the methods now with /m command, its lists the methods printString and method1 as well it shows the warning for the missing method2. After creating the method2, /m shows the methods printString, method1 and method2 without warnings. method_dep2.jpg
  8. Update the value of variable by assigning a new value to it. We can not change the type of a variable without declaring it again with the new type. Below image shows an example of updating an int variable and creating a new variable with the same name and different type; the int variable is removed in this caseupdate_var.jpg
  9. Edit the history of the statements with /edit command. When /edit is performed,  JShell Edit Pad (a pop up) comes with the history of the statements executed. We can edit one or more statements or can add/delete a statement. In the example shown below I have added a statement to include a new String variable, blogedit.jpgNow the list of variables shows the newly added String variable, blogedit_result.png
  10. Save all the statements executed to a file using /save file_name command . File extension can be anything. The saved file can be opened using /open filen_name
  11. Create a Class,  instantiate a class, call a method on the instance. Class.jpg

Jshell is a quick means to test code snippets. With the JShell java programmers are no more obliged to declare variables or methods inside a Class. JShell acts like a Unix shell for Java statements. 

Hope this article helped in giving you a good understanding of how to use JShell.

Stop writing obvious code for POJOs, use lombok’s @Data

Lombok helps in getting rid of the obvious code that we write when we define a class, instead it generates the obvious code at the time of compilation. Lets say if you are writing a plain vanilla bean to define a Car that has three attributes make, model and year you will define a class with these three variables and will define a no-argument constructor, setters and getters for all the variables. For any bean or POJO that you define, isn’t this code obvious that you always write? What if an annotation can generate all this code for you and you just define the class and its member variables.

The below screen shot of eclipse shows the java code for the class Car on the left side and the outline on the right side. It can be observed that the class definition doesn’t have the getters/setters, constructor or the other methods but the outline has them. The code is generated by the @Data annotation provided at the class level. The code looks amazingly precise.

Lombok Data
Class definition and methods generated by Lombok

Apart from the getters/setters, equals, hashcode and the constructors, @Data also generates a canEquals method; this checks if the given of the same type, precisely it performs instance of check. toString generates the string representation of the object in the format, classname(var1=valueofvar1 var2=valueofvar2 ... varn=valueofvarn) where var1 … varn are member variables of the class.

If a class has final variables, @Data generates a constructor with all the require arguments. For example, if you have a class like below,
@Data
public class CarWithFinalVariable {
private final String make;
private String model;
private int year;
}

lombok generates a constructor, public CarWithFinalVariable(String make)
When using lombok, I personally advice not to write additional constructors or methods inside a POJO. You may write one or more setter of you have to impose certain restrictions but for constructor it is strict NO NO. One should never write a code like below
@Data
public class CarWithFinalDontDoIt {
private final String make;
private String model;
private int year;
public CarWithFinalDontDoIt() {
make = null;
}
}

The no argument constructor here kills the purpose of the final variable, and eventually misguides the users of this class.

One of my favorites is toString because I don’t want to put my efforts in writing a method that serves no business purpose at the same time while debugging, when I hover the mouse over a variable I feel convenient to see the state of the object rather than seeing the object id and then go and expand to see the state. It is possible to configure the toString so as exclude the variables that you feel are trivial. Below is the example of excluding the variable make from toString
@Data
@ToString(exclude = "make")
public class CarConfigureToString {
private String make;
private String model;
private int year;
}

further reading
github url

Schema-less, Not model-less

The data model is not just the model of the data base tables, it represents more than that. Data model represents the domain model; the various entities that represents the a business. For  any product to be successful and to serve the intend purpose the data model is important, the data model is the common language among the end users, business teams and the developers. A poor data model leads to a poor understanding and the information gap between various stake holders.

The schema in the relational database terminology refers to the metadata or definition and organization of the various tables. The tables in the data base closely represent the data model. The schema is rigid, extending the data model becomes difficult. Involves transformation when such case arises. The positive side of this aspect is that it forces us to think of the schema, in a sense it mandates to understand the business thereby a data model. The data model helps in designing the Object/Entity model of the product.

The schema-less databases do not mandate a rigid schema and there by do not force us to think of a data model. I have observed a few occasions where teams started using the document databases and storing the data more in random format; mostly not able to relate between their object model and data base. Schema-less databases provide the flexibility for extending the model. The database accepts the any data to store but the application needs a model to operate.

One of the main advantages that comes out of using schema-less databases is that not requiring a Storage Model to Object Model conversion. If the project doesn’t have a well thought model, it may need to combine two or more entities from database to form a single Object. Having well defined model makes it easier to store and retrieval from a schema-less database. For example, a Java object can be converted to JSON and stored in MongoDB and retrieved and converted to Java object. If it has to come out of two documents, we accidentally have invited the relational databases’ complexity to the schema-less data bases as well.

The schema-less databases provide flexibility to add or remove more fields to the data, change the data type of the data, and obviates the need of normalization and relationships but they are not an excuse for not having a domain model.

Schema-less is not model-less.

What’s up with JUnit 5

JUnit 5 is not yet a GA release but it has started making the buzz around with its all new features, especially the Java8 enthusiasts like me couldn’t wait for the GA release to start using. Architecturally Junit 5 is a whole different animal than its predecessor; I will not talk about the architecture in this article instead will give a glimpse of how this new version of JUnit can improve the tests, if you are interested in understanding the JUnit 5 architecture I suggest a read of JUnit 5 user guide. 

The following are the changes or improvements over JUnit 4

  • There’s no difference in the way of writing basic tests, remains same as the JUnit 4
  • @Before and @After annotations are given new names @BeforeEach and @AfterEach without any change in the work they do
  • In the same lines as above @BeforeClass and @AfterClass are given new names @BeforeAll and @AfterAll; these are also unchanged with respect to the work they do or the constraints the the methods using these annotation need to meet
  • @Ignore got a new as well, @Disabled
  • Categorizing the tests has got a new annotation @Tag in place of @Category

The following are the new features added in Junit 5

  • A couple of years back we had a situation where the business team wanted to have a look at our unit test report with meaningful names. Then we had to create a custom annotation that holds the name of the test cases and used our implementation of RunListener to generate a meaningful report. JUnit 5 now provides the annotation @DisplayName that can be used to provide a name to the test. May sound like a trivial improvement but it really makes it’s case
  • @RepeatedTest annotation that is used to repeat a single test several times is another cool feature that comes handy when number of execution can change the state of an Object or to verify if the repeated execution causes any resource clog
  • Dependency Injection for constructors and the methods, which means the test methods as well as the methods annotated with @BeforeXXX and @AfterXXX can now take the arguments with the default runner. No need to fall back Parameterized class or the TestNG’s DataProviderRunner
  • Parameterized tests are now more flexible; one class can have different data sources, different methods can use different data sources. The test needs to be annotated with @ParameterizedTest and then with a source annotation like @ValueSource. There are different source annotations for different type of sources, will touch upon them in the upcoming articles.
  • Dynamic tests is another exciting feature. The tests are created at run time from a collection or stream of values as below. The dynamic test needs to be annotated with @TestFactory (Test Factory generated the tests at the run time). I will touch upon this in detail with code examples in upcoming articles

@TestFactory
Stream dynamicTestsFromStream() {
return Stream.of("your", "input/output", "values").map(
str -> dynamicTest("test" + s, "tr, () -> { /* A lambda of executable; This is where the test implementation goes */ }));
}

Note: It is to be noted that unlike the regular tests, before and after exeution of the dynamic tests the methods annotated with @BeforeXXX and @AfterXXX are not executed 

  • With JUnit 5, we can write a test class nested inside another test class. Inner class needs to be annotated with @Nested. This is particularly useful to group the tests but don’t want to write whole new outer class.

Hope you enjoyed reading this article, will comeback with the detailed articles about each of these cool features.