Java 8 StringJoiner

Introduction to Java 8 StringJoiner

In this short post, we will be covering Java 8 StringJoiner feature and will explore what are the different features and how this can be used more effectively with Java 8 Stream API.

 

Introduction 

Joining multiple strings in a very common tasks in day to day programming activity.There was no direct way to join multiple String in Java (Other than using the third party API’s). Java 8 Introduced a new class StringJoiner which can be used to join multiple Strings.StringJoiner is a kind of a Collector.

 

1. StringJoiner

StringJoiner is used to construct a sequence of characters separated by a delimiter and optionally starting with a supplied prefix and ending with a supplied suffix.

 1.1 Using Delimiter

One of the common use cases of the StringJoiner is to use a delimiter to join strings.

StringJoiner joiner = new StringJoiner(",");
    joiner.add("Sunday");
    joiner.add("Monday");
    joiner.add("Tuesday");

 System.out.println(joiner.toString());

Here is our Junit Test

@Test
public void stringJoinerTest(){

    StringJoiner joiner = new StringJoiner(",");
    joiner.add("Sunday");
    joiner.add("Monday");
    joiner.add("Tuesday");

    assertEquals("Sunday,Monday,Tuesday", joiner.toString());
}
 1.2 Using Delimiter, Prefix and Suffix

StringJoiner also provides the way to predefined prefix and suffix in addition to the delimiter.

public static void joinerWithDelimiterWithPrefixAndSuffix(){
    StringJoiner joiner = new StringJoiner(",", "Prefix-", "-Suffix");
    joiner.add("Sunday");
    joiner.toString();
}

Output 

Prefix-Sunday-Suffix

 

 1.3 Join Multiple StringJoiner

We can also merge multiple StringJoiner using StringJoiner’s merge() method

   StringJoiner joiner1= new StringJoiner("|");
   StringJoiner joiner2= new StringJoiner(";");
   StringJoiner joiner3= new StringJoiner(";");

   joiner2.add("one");
   joiner2.add("two");
   joiner1.merge(joiner2);

   joiner3.add("three");
   joiner3.add("four");
   joiner1.merge(joiner3);

   System.out.println(joiner1.toString());

Output

one;two|three;four

 

2. String.join()

StringJoiner is used internally by two static String.join methods

String output= String.join("-", "2017","09","30");
2017-09-30 //output
List<String> list= Arrays.asList("one","two","three");
String output = String.join("-", list);

one-two-three //output

4. Collectors.joining

StringJoiner can be easily used with the new Java 8 Collection API.

List<Customer> customers = Arrays.asList(
        new Customer("John", "Smith"),
        new Customer("Umesh", "Awasthi"),
        new Customer("Andy", "Flower")
);

final String customerJoin = customers.stream()
        .map(Customer::getFirstName)
        .collect(Collectors.joining(","));

System.out.println(customerJoin);

Output

John, Umesh, Andy

 

5. Why StringJoiner

There can be a very natural question about why do we need StringJoiner when we already have StringBuilder? Or it internally use StringBuilder to perform most of the operations

With the Java 8 Stream API, StringJoiner is very useful as compared to the StringBuilder.Let’s take an example to understand the difference between using SpringJoiner and StringBuilder.

List<String> list = Arrays.asList("Foo","Bar");

//join string using StringJoiner
String output = list.stream().collect(Collectors.joining(","));

//using StringBuilder

String collectoutput =
        list.stream().collect(Collector.of(StringBuilder::new,
                (stringBuilder, str) -> stringBuilder.append(str).append(", "),
                StringBuilder::append,
                StringBuilder::toString));

 

Summary

In this post, we got an Introduction to Java8 StringJoiner. We explored various features of the StringJoiner class and how to use it to join multiple Strings.We can also think of StringJoiner as a kind of Collector and can be really useful when working with parallel streams.

Convert a Map to List in Java

Convert a Map to List in Java

In this post, we will learn as how to Convert a map to List in Java.We will see how to do this using JDK.

 

1. Conventional Method

To convert, Java Map to List, we can use the conventional constructor with ArrayList, however, there are few things to consider before we proceed with the conversion. 

 Java Map has 2 values while list contains only single value while converting Map to list, we need to take a call of converting either map values or keys, so either we will get a map of keys or list of values (we can get both by using some wrapper to have both values).

public class MapToList {

    public static void main(String[] args) {

        Map<Integer,String> map= getMap();

        //Convert Map keys to List
        List<Integer> keyList= new ArrayList<Integer>(map.keySet());
        keyList.forEach(key-> System.out.println(key));

        //Convert Map values to List
        List<String> valueList= new ArrayList<String>(map.values());
        keyList.forEach(value-> System.out.println(value));

    }

    static Map<Integer,String> getMap(){

        Map<Integer, String> sampleMap=new HashMap<Integer,String>();
        sampleMap.put(1,"Sunday");
        sampleMap.put(2,"Monday");
        sampleMap.put(3,"Tuesday");
        sampleMap.put(4,"Wednesday");

        return sampleMap;
    }
}

Output for the above programme will be

1
2
3
4

For valueList

Sunday
Monday
Tuesday
Wednesday

2. Using Java 8

We can also use Java 8 Stream API to convert Map to List in Java.

public class MapToListJava8 {

    public static void main(String[] args) {

        Map<Integer,String> map= getMap();

        List<Integer> keyList=map.keySet().stream().collect(Collectors.toList());
        keyList.forEach(key-> System.out.println(key));

        List<String> valueList=map.values().stream().collect(Collectors.toList());
        valueList.forEach(value-> System.out.println(value));
    }

    static Map<Integer,String> getMap(){

        Map<Integer, String> sampleMap=new HashMap<Integer,String>();
        sampleMap.put(1,"Sunday");
        sampleMap.put(2,"Monday");
        sampleMap.put(3,"Tuesday");
        sampleMap.put(4,"Wednesday");

        return sampleMap;
    }
}

My preference will be for the constructor based approach as it is more straight forward and easy to read rather than the Java 8 Stream API.

3. Summary

In this post, we explored as to how to convert a Map to List in Java, we learned how to convert it using a constructor and Java 8 Stream API.We can use a similar technique to convert Map to Set which we will cover in another post.

All the code of this article is available Over on Github. This is a Maven-based project.

Java 9 New Features

 Java 9 New Features

In this articles, we will be covering Java 9 new features at a high level.We will explore these features along with details as what are the improvements happening to the existing features.

 

Introduction

Java 8 introduced a couple of new and exciting features like lambdas, streams and some of the API changes, Java 9 is coming up with rich feature sets like Jigsaw, Jshell (REPL),  collections and some API changes under the hood.In this, we will explore all Java 9 new features at a high level.You can get detail information of all Java 9 features available JDK 9.

 

1. Modular System – Jigsaw Project 

The modular system is one of the main and defining features of the Java 9.Jigsaw will be responsible for bringing much-needed modularity to the Java platform.One of the main reason to bring modularity to the Java provides modular JVM which can help us to run JVM on different devices with less memory. 

In another way, it’s a mechanism to run only modules and API required by a given application (e.g.application 1 need 3 modules to run completely while application 2 need only 1 module). 

Modules will be defined/ described in a file called module-info.java located at the top of our Java code hierarchy.

In order to understand Java 9 Modular system, let’s take an example of the Order placement process where we need OMS (Order Management System) to place an order but for rest of the use cases (e.g. Browsing site or adding products to the shopping cart), we might not need OMS for our application. We can have a web-based application which allows placing an order, however, we can have other channels which can place an order and we need OMS module to process these orders correctly. To achieve this, we can define 2 modules in Java 9 and can define required dependencies

module com.javadevjournal.shop.order {
    requires com.javadevjournal.erp.oms;
}

Here is a pictorial representation of the Java 9 Module system

Java 9 New Features
Java 9 Modules

Based on the requires statement, JVM will try to determine if it is able to resolve all modules. I strongly believe that Java 9 Modules feature will allow us to structure our application in a better way and will strongly enforce encapsulation and defined/ explicit dependencies.

 

2. JShell (REPL)

Many modern languages provide a tool (Mostly called as REPL or scripting tool) for real-time statement interpretation.One of the benefits of such tool is that you can easily test your code without creating a complete class or project.Java 9 will be introducing REPL or JShell which can be used to quickly run your code and compare results. 

For more details and video tutorial, please read Introduction to Java 9 REPL and JShell

 

3. G1 (Default Garbage Collector)

Java 8 has 4 different Garbage Collector and default Garbage Collector in Java 8 is Parallel / Throughput Collector. G1 will be the new default Garbage Collector in Java 9. G1 was designed for better performance and know to have less number of GC pauses. 

Get more insight of the all available Garbage Collectors and their feature in our other post Java Garbage Collector.

 

 

4. HTTP 2.0 Client

Java 9 is coming up with a new HTTP 2.0 based client which can also be taken as a replacement for the famous.HttpURLConnection Java 9 will be providing full support for new HTTP 2.0 and this new client will be supporting both HTTP/2 protocol and WebSocket.

This new API will be introduced as first incubator module in Java which means it will be introduced as an experimental feature and based on the feedback it will either be added as a full featured module in next release or will be removed from the Java platform.

HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
        .uri(new URI("www.travellingrants.com")).build();

HttpResponse<String> response = client.send(request,HttpResponse.BodyHandler.asString());

System.out.println(response.statusCode());
System.out.println(response.body());

It’s really easy and clean API, we no longer have to use InputStream or Reader and even our old friend.HttpURLConnection

HTTP 2.0 API also support an Asynchronous call by simply using HttpClient#sendAsync() method instead of HttpClient#send method.There is also option to cancel your request if server support HTTP/2.

 

5. StackWalker API

To put Stack Walk API  in Java 9 in simple words, It provides capabilities to walk through the stack in Java. StackWalker provides a snapshot of the current thread stack trace along with some methods to access it.

Please read our article StackWalker API In Java 9 to get more insight for this new Java 9 feature.

 

6. Process API

Before Java 9 there was a limited support for controlling and managing operating systems processes, even getting hold of simpler OS related process was not a simple one liner solution and require a lot of workarounds.

Java 9 is introducing a lot of improvements to process API for controlling and managing OS related process.

java.lang.ProcessHandle class contains most of the new features of the process API. To get an understanding let’s take an example of getting PID in both Java 8 and Java 9

Java 8
public static void getProcessIdByJava8(){

    try {
        String[] args = new String[] { "/bin/sh", "-c", "echo $PPID" };
        Process p = Runtime.getRuntime().exec(args);
        InputStream p_out = p.getInputStream();
        String s = (new BufferedReader(new InputStreamReader(p_out))).readLine();
        p.destroy();
        if (s != null)
            System.out.println(s);
    } catch (IOException e) {
        e.printStackTrace();
    }
   
}

Java 9
public static void getProcessIdByJava9(){
    System.out.println("Your Process id is :" + ProcessHandle.current().pid());
}

As we saw, getting operating system information using Java 9 process API is quite easy and clean.It gives Java developer an API to interact with the operating system and can be used to get information on the status of the JVM.

We can get a lot of other information from the process API. Read here for more details.

 

7.  Collection Factory Methods

Collection Factory Methods are introduced in Java 9 like Scala. Static methods have been provided by Java 9 on List, Set and Map interfaces which can easily returned unmodifiable collections by calling of() method of the respective interface.

For more detail, please read Collection Factory Methods in Java 9

 

8. Try With Resources Improvement

Java 7 introduced try-with-resources for managing resources automatically and to ensure that resources will be closed after execution of the program.

Before Java 9, in order to use try-with-resources, we will have to use something like this

try (BufferedReader br = new BufferedReader(new FileReader("/input.txt"))) {
    String line;
    while (null != (line = br.readLine())) {
        // processing each line of file
        System.out.println(line);
    }
} catch (IOException e) {
    e.printStackTrace();
}

Or we will be using a very similar syntax, Above syntax provide a lot of features and auto management of the resources, however, we still need to declare a local variable to work with, Java 9 is a further refinement to this feature to avoid verbosity.

 

BufferedReader br = new BufferedReader(new FileReader("/input.txt"));

// Java 9 make it simple
try (br) {
    String line;
    while (null != (line = br.readLine())) {
        // processing each line of file
        System.out.println(line);
    }
} catch (IOException e) {
    e.printStackTrace();
}

 

9. Interface Private Method

Java 8 came with certain enhancement while declaring interfaces, few of those features are

  1. Method implementation in interface using default and static methods

However, it still not provide a way to create a private method in Interface. Java 9 will provide a way to have a private method in an interface.This feature will really be useful to avoid redundant code and promote code reusability.

public interface PrivateMethodExample {

    private static String getDBDetails(){
        return "MySQL";
    }

    private boolean checkConnection(String DBDetails){
        return  DBDetails.equalsIgnoreCase("MySQL") ? true : false;
    }

    default void checkDBConnection(){
        String dbName = getDBDetails();
        boolean isAlive =   checkConnection(dbName);  
    }
}

 

10. Мulti-Resolution Image API

Java 9 will be introducing a new API defined under java.awt.image package, it will allow a set of images with different resolutions to be encapsulated into a single multi-resolution image.

For more details read Multi-Resolution Images.

 

 

11. Miscellaneous Java 9 Features

There are other features introduced in Java 9 which I will be covering in another post in more details, here is the list of some of the other features introduced in Java 9

  1. Improvement to Optional API. Read java 8 optional to get a basic understanding of Optional API introduced in Java 8.
  2. Unified JVM Logging.
  3. Stream API Improvement.
  4. Reactive Streams
  5. CompletableFuture API Improvements
  6. Improved Javadoc

 

Summary

In this post, we covered  Java 9 new features. Java 9 is coming up with modular JVM which is going to be one of the defining features of Java 9 along with a number of improvements in the JDK.

Convert a Map to Set in Java

Convert a Map to Set in Java

In this post, we will learn as how to Convert a Map to Set in Java.We will see how to do this using JDK.

 

1. Conventional Method

To convert, Java Map to Set, we can use the conventional constructor with HashSet, however, there are few things to consider before we proceed with the conversion. 

 Java Map has 2 values while Set contains only single value while converting Map to Set, we need to take a call of converting either map values or keys, so either we will get a set of keys or set of values (we can get both by using some wrapper to have both values).

public class MapToSet {

    public static void main(String[] args) {

        Map<Integer,String> map= getMap();

        //Convert Map keys to Set
        Set<Integer> keySet= new HashSet<Integer>(map.keySet());
        keySet.forEach(key-> System.out.println(key));

        //Convert Map values to Set
        Set<String> valueSet= new HashSet<String>(map.values());
        valueSet.forEach(value-> System.out.println(value));

    }

    static Map<Integer,String> getMap(){

        Map<Integer, String> sampleMap=new HashMap<Integer,String>();
        sampleMap.put(1,"Sunday");
        sampleMap.put(2,"Monday");
        sampleMap.put(3,"Tuesday");
        sampleMap.put(4,"Wednesday");

        return sampleMap;
    }
}

Output for the above programme will be

1
2
3
4

For valueMap

Sunday
Monday
Tuesday
Wednesday

2. Using Java 8

We can also use Java 8 Stream API to convert Map to Set in Java.

public class MapToSetJava8 {
    public static void main(String[] args) {

        Map<Integer,String> map= getMap();

        Set keySet=map.keySet().stream().collect(Collectors.toSet());
        keySet.forEach(key-> System.out.println(key));

        Set valueSet=map.values().stream().collect(Collectors.toSet());
        valueSet.forEach(value-> System.out.println(value));
    }

    static Map<Integer,String> getMap(){

        Map<Integer, String> sampleMap=new HashMap<Integer,String>();
        sampleMap.put(1,"Sunday");
        sampleMap.put(2,"Monday");
        sampleMap.put(3,"Tuesday");
        sampleMap.put(4,"Wednesday");

        return sampleMap;
    }
}

My preference will be for the constructor based approach as it is more straight forward and easy to read rather than the Java 8 Stream API.

3. Summary

In this post, we explored as to how to convert a Map to Set in Java, we learned how to convert it using a constructor and Java 8 Stream API.Please read  … to see how to convert Map to List in Java

All the code of this article is available Over on Github. This is a Maven-based project.

Join multiple lists in Java

How to Join multiple lists in Java

In this short post, we will learn how to join multiple lists in Java. We will be covering how to do this in Java 8, Java 7 and how we can use Apache Common API to join these lists.

 

1.  Using  Java 8 Stream API

Java 8 Stream API provides a couple of different options to join multiple lists. We will be exploring concat() and flatMap() method provided by the Stream API.

 

1. 1 Using  Concat method

We can use concat() method to combine two streams, concat() method will work by contacting all elements of the first stream with the second stream.

public class JoinListJava8 {

    public static void main(String[] args) {

        List<String> listA= asList("A", "B","C");
        List<String> listB=asList("C","D","E","F");

        concactStream(listA,listB);
    }


    public static void concactStream(List<String> listA, List<String> listB){

        List<String> newList= Stream.concat(listA.stream(),listB.stream()).collect(Collectors.toList());
        newList.forEach(item-> System.out.println(item));
    }


}

Output


A
B
C
C
D
E
F

In case we have more than 2 Streams to combine, we can use concat() method within original method

Stream.concat(Stream.concat(c.stream(), c2.stream()), c3.stream());
 
1. 2 Using  flatMap method

In case we have a number of lists, we can use flatMap() method to join multiple lists in Java.flatMap method will return a Stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element.

Please read Stream#flatMap for more detail

 

public class JoinListJava8 {

    public static void main(String[] args) {

        List<String> listA= asList("A", "B","C");
        List<String> listB=asList("C","D","E","F");

        flatMap(listA,listB);
    }


    public static void flatMap(List<String> listA, List<String> listB){

        List<String> newList= Stream.of(listA,listB).flatMap(Collection::stream).collect(Collectors.toList());
        newList.forEach(item-> System.out.println(item));
    }

}

 

2.  Using  Java 7 

If you are not using Java 8 and do not want to use any third party API (like Apache Common Collections or Guava), you can use addAll() method to accomplish your goal. You need to call addAll() method multiple times to join lists in Java.

public class JoinListJava7 {

    public static void main(String[] args) {

        List<String> listA= asList("A", "B","C");
        List<String> listB=asList("C","D","E","F");

        List<String> listC = new ArrayList<String>();
        listC.addAll(listA);
        listC.addAll(listB);

        //print results

        for(String output: listC){
            System.out.println(output);
        }
    }
}

You can even shorten above code by using 

List<String> listC = new ArrayList<String>(listA);
listC.addAll(listB);

 

3. Apache Commons Collections

Apache Commons Collections API provides utility methods to join multiple lists in Java.

public class JoinListApacheCommons {

    public static void main(String[] args) {

        List<String> listA= asList("A", "B","C");
        List<String> listB=asList("C","D","E","F");

        Iterable<String> newList= CollectionUtils.union(listA,listB);
    }
}

 

4. Summary

In this post, we discussed how to join multiple lists in Java. We covered how to do it in JDK using Java 7 and Java 8 along with an option to use Apache Common Collection API.

All the code of this article is available Over on Github. This is a Maven-based project.

JVM Parameters

Introduction to JVM Parameters

In this post, we will be covering some of the most important and critical JVM Parameters which can be used to configure and fine tune JVM.

Performace of the JVM depends on the factor as to how well JVM is configured for a given application. Let’s cover few of the well known JVM parameters to start with. 

 

This post will serve as a starting point to understand some of the key parameters for the JVM, this post does not cover advanced JVM optimization techniques.

 

1. Heap Memory

One of the main optimization features involves assigning correct heap size to the JVM based on our application. It is recommended to specify minimum and maximum heap size to the JVM

1.1 -Xmxsize (Maximum Heap Size)

Xmx is used to specify the maximum size of the memory, to specify maximum heap size, we can use the following convention

-Xmx<Heap Size>[Unit]

HeapSize denotes the size of the heap and should be multiple of 1024.Unit indicates the unit of the memory in which we want to specify to the JVM.Append the letter k or K to indicate kilobytes, m or M to indicate megabytes, g or G to indicate gigabytes.

For example, if we want to assign maximum of 6GB to our JVM, all of the following parameters are valid

-Xmx6442450944
 -Xmx6000m
 -Xmx6G

 

1.2 -Xmssize (Minimum Heap Size)

Xms is used to specify the minimum size of the memory, to specify minimum heap size, we can use the following convention

-Xms<Heap Size>[Unit]

HeapSize denotes the size of the heap and should be multiple of 1024.Unit indicates the unit of the memory in which we want to specify to the JVM.Append the letter k or K to indicate kilobytes, m or M to indicate megabytes, g or G to indicate gigabytes.

For example, if we want to assign minimum of 4GB to our JVM, all of the following parameters are valid

-Xms4294967296
 -Xms4000m
 -Xms4G

 

For assigning minimum 4GB and maximum 6GB to JVM, we can use following parameters.

-Xms4G -Xmx6G

 

1.3  -XX:NewSize=size (Young Generation Heap Size)

To understand this parameter, we need to understand about young generation region in the heap, young generation region of the heap is used for new objects and due to it, this is known as one of the most important JVM parameters apart from -Xmx and -Xms.

Keep in mind that GC (Garbage collection) is performed more often in this region of the memory, so this needs special consideration as if the size is too low, then JVM will perform a large number of minor GC operation and if size is too large a full GC will be performed which can be time-consuming, this entire activity can have a major impact on the application based on the configured GC. 

We can use the following convention to set size for young generation

-XX:NewSize=<young size>[k|m|G]

For example, to set initial size of the young generation to 1GB, we can use one of the following conventions

-XX:NewSize=1024m
 -XX:NewSize=1G 

We can use -XX:MaxNewSize=size to set a maximum size of the heap for the young generation.

Following JVM parameters has been removed from Java 8, setting those parameters will not perform any modification or optimization to the JVM. It is recommended not to use these parameters -XX:MaxPermSize=size
-XX:PermSize=size

 

2. Garbage Collection Options

Garbage collector can play a vital role in your application and choose a correct Garbage Collector (GC) is really important. JVM provide following type of Gargabe collector

  • Serial Garbage Collector (XX:+UseSerialGC)
  • Parallel Garbage Collector (XX:+UseParallelGC)
  • CMS Garbage Collector (XX:+USeParNewGC)
  • G1 Garbage Collector (XX:+USeG1GC)

Please read  Java Garbage Collector for more details.

 

3. Java Garbage Collection Log (GC Logging)

To debug memory issues or application performance, We can enable GC logging in JVM. GC log provides a lot of information and statics about the Garbage collection process, some of the information (but not limited) provided by GC logging are

  • How Long GC Run
  • Information about when full GC run.
  • Information about the JVM pause when GC was running.
  • Information about Young and Old generation regions.

To understand GC logging, we need to enable GC log in the JVM

3.1 -XX:+PrintGCDetails (Print GC details Messages)

This option is disabled by default, we need to use this flag to enable printing detail messages at every GC.

3.2 -XX:+PrintGCDateStamps (Print GC details Messages)

Can be used for the printing of a date stamp at every GC, this option is also disabled by default.

3.3 -Xloggc:filename

This can be used to set file name and location to which GC output will be redirected.

3.4  -XX:+UseGCLogFileRotation

Should be used to enable log rotation.This can be really helpful for handling large log files produced by long running Java Applications.This property must be used with -Xloggc:<filename>.

3.5  -XX:NumberOfGClogFiles=<number of files>

Sets the number of files to use when rotating logs, default value is 1 and it should be always >=1

3.6 -XX:GCLogFileSize=<number>M (or K)

Defines the size of the log file at which point the log will be rotated, default will be set to 512K

Here is an example with above configurations

-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:/home/DATA/gc.log
-XX:+UseGCLogFileRotation
-XX:NumberOfGCLogFiles=5
-XX:GCLogFileSize=20M

Please note that using  +PrintGCDateStamps can add some overhead since an additional thread will be required to monitor system time.

 

4. -Dproperty=value (32 /64 bit)

Sets a system property value. The property variable is a string with no spaces that represents the name of the property.To run an application on 32 or a 64-bit environment, we can use this property as

-d<OS bit>

e.g. -d32 for 32-bit environment or -d64 for 64-bit environment.

 

5. Additional Properties

-server : Selects the Java HotSpot Server VM.For 64 bit, this option is implicit.

-XX:MaxHeapFreeRatio=percent : Sets the maximum allowed percentage of free heap space after a GC event (e.g. -XX:MaxHeapFreeRatio=75 for setting maximum free heap ratio to 75%:)

-XX:MaxMetaspaceSize=size : Sets the maximum amount of native memory that can be allocated for class metadata, there is no limit by default and it will be dependent upon the size/type of application. (-XX:MaxMetaspaceSize=512m to set maximum class meta data size to512 MB)

XX:SurvivorRatio=ratio : Sets the ratio between Eden space size and survivor space size.

 

Summary

In this post, we covered some of the main JVM Parameters which can be used to optimize and configure JVM based on our application. As mentioned in the beginning this post just outlines few of the important JVM Parameters. Please refer to Java HotSpot VM Options for more details (Please refer to correct JDK version for updated list).

Split a String in Java

Split a String in Java

In this small post, we will explore how to split a string in Java.

 

Introduction

Splitting a String in Java is a very common operation, we will discuss different method available in Java to split a String.

 

1. String#split() Method

Java String class provide a convenient and easy split() method to split String a String.The split method comes in 2 flavours and takes a regular expression as an input. Split method is powerful and mostly sufficient for most use cases.

public void split(){
    String input = "This-is-a-sample-input";
    String[] parts= input.split("-");
    for(int i =0; i< parts.length;i++){
        System.out.println(parts[i]);
    }
}

If you want to limit the number of resulting parts, you can pass the second argument (limit) to the split method.The limit parameter controls the number of times the pattern is applied and therefore affects the length of the resulting array. Here is an another variation of the above example

public void splitWithLimit(){
    String input = "This-is-a-sample-input";
    String[] parts= input.split("-", 2);
    for(int i =0; i< parts.length;i++){
        System.out.println(parts[i]);
    }
}

If you run above example, output will be

This
is-a-sample-input

Please note that split() method takes a regular expression as an input and we need to escape special character if needed (Please check different special character available in regular expression ). We can use \ to escape special characters or Pattern.quote() for it.

 

2. Split String Using Java 8

With Java 8, we can use Stream and Collector to split String. Here is a simple code to split a string in Java 8

public void splitStringJava8(){
    String input = "This-is-a-sample-input";
    List<String> parts = Pattern.compile("-")
                         .splitAsStream(input)
                         .collect(Collectors.toList());
    parts.forEach(s-> System.out.println(s));
}

 

3. Split String Apache Utils

Apache StringUtils provide null safe methods to split a string, here is a sample code for the same

public void apacheStringUtils(){
    String input = "This-is-a-sample-input";
    String[] parts =StringUtils.split(input ,"-");
    for(int i =0; i< parts.length;i++){
        System.out.println(parts[i]);
    }
}

In case you are not passing any delimiter to above method, whitespace will be taken as a default delimiter by it.

 

Conclusion

In this post, we saw different methods to split a string in Java including methods available in Apache’s StringUtils class. I believe that for most of the case split() method provided by the String class will serve our purpose.

 

All the code of this article is available Over on Github. This is a Maven-based project.

Iterate through a Map in Java

How to iterate through a Map in Java

In this articles, we will explore the different ways to Iterate through a Map in Java. We will start with a simple use case and will explore how we can do this using Java 8 Stream API.

 

Introduction

Iterating through Java Map is very common tasks and we face this tasks daily basis. Java Map API provides keySet(), valueSet() or entrySet() option to fetch content/data from the Map.

The Map.entrySet method returns a collection-view of the map, whose elements are of this class. The only way to obtain a reference to a map entry is from the iterator of this collection view. These Map.Entry objects are valid only for the duration of the iteration.

Entry.getKey() returns the key corresponding to this entry. Let’s explore different options to Iterate through a Map in Java.

 

Example

To start working on the different options, let take a simple Map contains few values. Here is code for the simple Map.

Map<String, String> sampleMap= new HashMap<String,String>();

sampleMap.put("one", "one");
sampleMap.put("two", "two");
sampleMap.put("three", "three");
sampleMap.put("four", "four");
sampleMap.put("five", "five");
sampleMap.put("six", "six");

1.  EntrySet with for Loop 

public void iterateForEach(Map<String, String> sampleMap){
    for(Map.Entry<String,String> mapValue : sampleMap.entrySet()){
        System.out.println(mapValue.getKey()+" :" + mapValue.getValue());
    }
}

In above code, we have we converted Map to entry set and then we iterated through the entries using for each loop.

2.  EntrySet with for Loop 

If you don’t want to use For Each loop, we can convert entrySet() to the iterator and use an iterator to loop through the map content.

public void iterator(Map<String, String> map){
    Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
    while(iterator.hasNext()){
        Map.Entry<String, String> entry = iterator.next();
        System.out.println(entry.getKey()+" :" + entry.getValue());
    }
}

I will not prefer this approach and will go with for each loop.

3.  For Each with Java 8 Lambdas

The introduction of Lambdas in Java 8 provides a more concise and easy to read solution.

public void lambdas(Map<String, String> map){
    map.forEach((key,value) ->System.out.println(key + ":"+ value));
}

One of the interesting thing with above approach is that we don’t need to convert the map to entry set for iteration.

4.  Java 8 Stream API

Stream was introduced in Java 8 as one of the main features, we can use Stream API to iterate through the map.

public void stream(Map<String, String> map){
    map.entrySet().stream().forEach(entry-> System.out.println(entry.getKey() +": "+entry.getValue()));
}

I will not use this since we are converting Map to entry set and iterating through the element which is more or less equivalent to for each loop.

If you want you can use Java 8 Stream API parallel method but I will not cover that in this post.

5.  Performance

For small map size (<=100), Java 8 based for each loop have the best performance. In the case of Map size is greater than 10000 elements, simple for each loop seems to be faster than other approaches.Please execute your own benchmarking before taking a call for your implementation.

6.  Conclusion

In this short post, we covered some of the methods to Iterate through a Map in Java along with few options provided by Java 8. 

All the code of this article is available Over on Github. This is a Maven-based project.

Java NIO2 File Attributes

Introduction to Java NIO2 File Attributes API

In this post, we will cover Java NIo2 File Attributes. File attributes are also known as metadata. Metadata can be used to find out information about the file systems like if it’s a regular file or a directory, who is the owner of the file or directory.

I have already covered Java NIO2Java NIO Path and Java NIO Selector as part of the new NIO features introduced in Java 7. 

 

Introduction

File metadata can be used to get information about the file ranging from the size of the file to the access permissions. These File Attributes can be used to check critical information before moving ahead with real file-based operations. 

I will be covering different metadata attributes in this post.

 

1.   Basic File Attributes

To get information about all the basic attributes of the file, we can use Files.readAttribute() method. This method will return BasicFileAttributes which can be used to access various basic file attributes.This approach is more efficient as we are not required to make a separate call to the underlying file system to read individual attributes.

We will get BasicFileAttributes for a given path and then check what all information we can get from this

Path path = Paths.get("/Users/umesh/personal/tutorials/source");
BasicFileAttributeView fileAttributeView = Files.getFileAttributeView(path, BasicFileAttributeView.class);
BasicFileAttributes basicFileAttributes = fileAttributeView.readAttributes();

We first retrieved BasicFileAttributeView and retrieved.BasicFileAttributes from it.We went this route since BasicFileAttributeView contains set of file attributes consist of mandatory and optional file attributes as defined by the BasicFileAttributes interface.

Once we have BasicFileAttribute, we can get all basic file attribute information from it.

1.1   Check Creation Time

To find creation time of the file, use creationTime() method

basicFileAttributes.creationTime()

 

1.2  Last Access Time

basicFileAttributes.lastAccessTime()

 

1.3  Check for Directory

We can also check if a given path is a file or directory 

basicFileAttributes.isDirectory()

 

1.4  Basic Attribute Example

Here is complete example demonstrating various methods available to get basic file information.

Path path = Paths.get("/Users/umesh/personal/tutorials/source");
BasicFileAttributeView fileAttributeView = Files.getFileAttributeView(path, BasicFileAttributeView.class);
BasicFileAttributes basicFileAttributes = fileAttributeView.readAttributes();

System.out.println("creationTime: " + basicFileAttributes.creationTime());
System.out.println("lastAccessTime: " + basicFileAttributes.lastAccessTime());
System.out.println("lastModifiedTime: " + basicFileAttributes.lastModifiedTime());

System.out.println("isDirectory: " + basicFileAttributes.isDirectory());
System.out.println("isOther: " + basicFileAttributes.isOther());
System.out.println("isRegularFile: " + basicFileAttributes.isRegularFile());
System.out.println("isSymbolicLink: " + basicFileAttributes.isSymbolicLink());
System.out.println("size: " + basicFileAttributes.size());

All method related to getting time returns FileTime object which is different than simple TimeStamp 

2.  File Owner Information

In order to get high-level file ownership information, We can use FileOwnerAttributeView provided by Java NIO2 API.

FileOwnerAttributeView fileOwner=Files.getFileAttributeView(path, FileOwnerAttributeView.class);
System.out.println("File Owner Name " +fileOwner.getOwner());

You can get information about the POSIX or DOS file attributes by passing DosFileAttributes.class or PosixFileAttributes.class to Files.getFileAttributeView() method.

 

3. File Store Attributes

Java NIO2 API provides a convenient FileStore class to get information about the file. We can use this class to get information about the underlying file system like how much space is available, how much used etc. 

FileStore store = Files.getFileStore(path);

long total = store.getTotalSpace() / 1024;
long used = (store.getTotalSpace() - store.getUnallocatedSpace()) /1024;
long available = store.getUsableSpace() /1024;

Summary

In this post, we covered basics as how to get information about the basic file attributes using Java 7 NIO2 File Attributes.

 

All the code of this article is available Over on Github. This is a Maven-based project.

Java Base64 Encoding and Decoding

Java Base64 Encoding and Decoding

In this post, we will explore various options of Java Base64 Encoding and Decoding. We will be covering mainly new Base64 API introduced in Java 8.

 

Introduction

Base64 encoding was missing from standard JDK before Java 8. Java 8 introduced a simple yet powerful API under java.util package or specifically a utility class java.util.Base64. In this post, we will be covering Java Base64 encoding and decoding.

The Base64 class consists of static factory methods for obtaining Base64 based encoder and decoder. We can obtain following 3 types of Base64 encoder/ decoder

  1. Basic
  2. URL and FileName
  3. MIME 

 

1.  Java 8 Basic Encoder

Java 8 Basic Base64 encoder is a simple encoder.It will simply encode without adding any line feed/line separator characters. 

void basicEncoder(final String input) {
    String simpleBase64 = Base64.getEncoder().encodeToString(input.getBytes(StandardCharsets.UTF_8));
    System.out.println(simpleBase64);
}

The output of the encoder will be mapped to characters in the Base64 Alphabet: A-Za-z0-9+/ and it will reject data that is outside this base64 alphabet.

 

1.1  Java 8 Basic Decoder

Decoding encoded String back to original form is quite simple with new API, all we have to do it to get encode and pass decoded data to it.

void basicDecoder(final String encodedData) {
    byte[] decodeData = Base64.getDecoder().decode(encodedData);
    System.out.println(new String(decodeData, StandardCharsets.UTF_8));
}

We are no longer required to use those external dependencies (e.g. Sun classes etc) to do encoding and decoding. 

2.  URL Encoding

URL encoding works very similarly to Basic encoding and it uses “URL and Filename safe Base64 Alphabet”. 

String input= "search?_base64";
void urlEncoding(final String input) {
    String urlEncode= Base64.getUrlEncoder().encodeToString(input.getBytes(StandardCharsets.UTF_8));
    System.out.println("Encoding using URL Encoder "+urlEncode);
}

2.1  URL Decoder

URL decoder work in a similar way as encoder work, we need to get UrlDecoder() and pass the encoded data to it.

void urlDecoding(final String encodedData) {
    byte[] decodeData = Base64.getUrlDecoder().decode(encodedData);
    System.out.println(new String(decodeData, StandardCharsets.UTF_8));
}

3.  MIME Encoding

MIME encoding will use Base64 encoding using Basic Alphabet and encoded output will be converted into MIME format (no more than 76 characters each and uses a carriage return ‘\r’ followed immediately by a linefeed ‘\n’ as the line separator).

private static void mimeEncoder(){
    StringBuilder stringBuffer = new StringBuilder();
    for (int t = 0; t < 10; ++t) {
        stringBuffer.append(UUID.randomUUID().toString());
    }

    String mimeEncoding = Base64.getMimeEncoder().
                          encodeToString(stringBuffer.toString().getBytes(StandardCharsets.UTF_8));

    System.out.println("MIME Encoding is " +mimeEncoding);
}

Output

MIME Encoding is:: ZjY5NzBkYTctMDFmNy00YmY3LTk4YjAtMmYxZGUzYzNhM2QwZTNmM2I4M2EtODg0Yy00ZjlkLTlm
YTgtMjIzZWY1ZTMzNGQ2ODVlZDA0ZDQtMjJjMy00NzUxLWEwYTYtYzM2ZTNhOTFjNzk0MmEwY2Iz
ZDYtYmRmNC00MmUzLTllMzQtZjIzMDRkMmMxMzgyMmIxNTExZjEtZDdkYS00ZjIwLTlhMzUtYjYy
ZTFiNTc3ZmQ1NzM3NDViM2ItNTRkMC00MTM4LTgxMjMtNmQ4ZDgyMzRlYTI4YTA1NjFhMGEtNWY3
NC00NDdmLTlhNWItOWIxNTgxOWY4NzJlMTRhZThmN2MtNjdiOS00ZDcwLWEwZmYtOGEyNjM3MDBm
NzNlMTRiNzdiY2YtYWI2ZS00MmNmLWI5NjAtMjFmZThmZjZmMmJjYWU0MmQ0MmUtZDE1ZC00NTdk
LThmMzUtNTUyMTlhMzRiMmYx

2.1  MIME Decoder

byte[] decodeData = Base64.getMimeDecoder().decode(encodedData);
System.out.println(new String(decodeData, StandardCharsets.UTF_8));

 

4.  Conclusion

In this post, we explored  Java Base64 Encoding and Decoding API introduced in Java 8. This new API is simple and powerful and at the same time will be available within the JDK without the need for external dependencies (commons-codec or sun.misc.BASE64Decoder).

All the code of this article is available Over on Github. This is a Maven-based project.

References

Base64