Tuesday, 31 January 2017

Generics in Java

There have been many new feature additions in Java over the year, with introduction of lambda expression in Java 8 it has even moved toward functional programming. But long before the lambda expressions and stream API there was one change which had a very big impact on the way you program and that was generics which was added in Java 5.

Generics not only added a new way to declare classes, methods or interface but it also changed many of the classes in the API, Java collections API is an example.

Initially it took some time getting used to the parameters like T, K or V with the classes or methods but now its quite a familiar thing and very much a part of your daily programming.

Generics

Generics enable you to specify type parameters when defining classes, interfaces and methods. Here type parameter is the type of data (class or interface) which these classes, interfaces and methods will operate upon.

As example, when you say List<T> that means a list which will store elements of type T. Since you have specified a type parameter so this List class is generic and T is the type parameter which specifies the type of element stored in the List.

Generic class format

A generic class is defined with the following format:

is defined with the following format:

class name<T1, T2, ..., Tn> { 
    /* ... */ 
}

The type parameter section, delimited by angle brackets (<>), follows the class name. It specifies the type parameters (also called type variables) T1, T2, ..., and Tn.

Type Parameter Naming Conventions

By convention, generic type parameter names are single, upper case letters. That helps n distinguishing between type parameters and normal variables.

The most commonly used type parameter names are:

  • E - Element (used extensively by the Java Collections Framework)
  • K - Key
  • N - Number
  • T - Type
  • V - Value
  • S,U,V etc. - 2nd, 3rd, 4th types

Benefits of Generics

You might be thinking there is already an Object class which provides almost the same thing, as Object is super class of all the other classes so Object class can be used to make a class generic. Though that can be done but it may cause some unseen problems because there is no type safety.

As example -

Let’s say you have a list where you intended to store strings and you have not made it generic that means all its elements will be stored as objects of type Object -

List strList = new ArrayList();
strList.add("a");
strList.add("b");
strList.add(new Integer(4));
Iterator itr = strList.iterator();
while(itr.hasNext()){
 String str = (String)itr.next();
 System.out.println("" + str);
}

Since elements are stored as class Object type so there won’t be any compile time error if you store an integer too (as done in this line strList.add(new Integer(4));), even if you intended to store Strings.

Since the elements are stored as class Object type so you need to cast those elements to String while retrieving. At that time you will get a run time exception when the code will try to cast Integer to String.

So the code snippet shown above will throw run time exception -
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

That brings to the fore couple of benefits of using generics -

  • Stronger type checks at compile time - In the above code if you use generics and specify the parametrized type of List as String you will get compile time error if an attempt is made to add element of any other type to the list. A Java compiler applies strong type checking to generic code and issues errors if the code violates type safety. Fixing compile-time errors is easier than fixing runtime errors, which can be difficult to find.

    As example -

    List<String> strList = new ArrayList<String>();
    strList.add("a");
    strList.add("b");
    strList.add(new Integer(4));
    

    With generics this code will throw following compile-time error if you try to add Integer to the list
    The method add(String) in the type List<String> is not applicable for the arguments (Integer)

  • Casting is not required - Another benefit you get is cast is not required. Since you already specify the type with generics so explicit cast is not required.

    As example-

    List<String> strList = new ArrayList<String>();
    strList.add("a");
    strList.add("b");
    strList.add("c");
    
    Iterator<String> itr = strList.iterator();
    while(itr.hasNext()){
        String str = itr.next();
        System.out.println("" + str);
    }
    

    Here you see casting is not required when retrieving elements from the list.

  • Enabling programmers to implement generic algorithms – In many algorithms, logic remains same, irrespective of the data they are used with. On the other hand, generics make it possible to write classes, methods and interface that work with different kind of data that too in a type safe manner. Now combine these two facts and the result is being able to write generic algorithms that work with any type of data.

    As example-

    Let’s take a simple example to see how to create a generic class with parametrized type. While creating an object of the class you can specify the type, which in generics terminology is called generic type invocation, which replaces T with some concrete value.

    Generic class

    public class GenType<T> {
        T obj;
    
        public T getObj() {
            return obj;
        }
    
        public void setObj(T obj) {
            this.obj = obj;
        } 
    }
    

    Using Generic class

    public class GenericDemo {
    
        public static void main(String[] args) {
            // With Integer type
            GenType<Integer> genInt = new GenType<Integer>();
            genInt.setObj(21);
            int value = genInt.getObj();
            System.out.println("integer value " + value);
            
            // With String type
            GenType<String> genStr = new GenType<String>();
            genStr.setObj("Generic class test");
            String str = genStr.getObj();
            System.out.println("String value " + str);
            
            // With Double type
            GenType<Double> genDouble = new GenType<Double>();
            genDouble.setObj(34.56);
            double dblValue = genDouble.getObj();
            System.out.println("Double value " + dblValue);
        }
    }
    

    Output

    integer value 21
    String value Generic class test
    Double value 34.56
    

    Here you see that the same generic class is first invoked with Integer type, then String and then Double. And you get the added benefit of type safety and no chance of run time exception (which is a probability if you had used an Object class to make the class generic).

Points to remember

  1. Generics provide type safety as there are stronger type checks at compile-time.
  2. Generics don’t work with primitive types, type arguments passed to the type parameters must be references.
  3. You can have generic classes, generic methods and generic interfaces.
  4. Type parameters are erased when generic classes are compiled.
  5. A generic class with type parameters can’t have static members using the type parameter. As example -
    public class GenType<T> {
        static T obj;
          .....
        .....
    }
    
    This code will have compile-time error - Cannot make a static reference to the non-static type T.
  6. In Java 7 and later you can replace the type arguments required to invoke the constructor of a generic class with an empty set of type arguments (<>) as long as the compiler can determine, or infer, the type arguments from the context. This pair of angle brackets, <>, is informally called the diamond.
    As example - List<Integer> ls = new ArrayList<>();
    With arraylist you don’t need to write <Integer> again, empty set of type argument (<>) will do, type will be inferred automatically.

That's all for this topic Generics in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Bounded type parameter in Java generics
  2. Generic class, interface and generic method
  3. Wildcard in Java Generics
  4. varargs in Java
  5. covariant return type in Java
  6. Parallel Stream in Java Stream API

You may also like -

>>>Go to Java advance topics page

Friday, 27 January 2017

Using depends-on attribute in Spring

If one bean is a dependency of another that usually means that one bean is set as a property of another. In Spring framework, typically you accomplish this with the <ref/> element in XML-based configuration metadata.

Quite infrequently you may have a situation where one bean does not explicitly depend on another bean meaning it is not referred in another class as a property or a constructor argument. But one of the bean still depends on another bean and requires another bean to be initialized before its own initialization.

As example, a static initializer in a class needs to be triggered, such as database driver registration.
In that case you can use depends-on attribute. The depends-on attribute can explicitly force one or more beans to be initialized before the bean using this element is initialized.

As example -

Suppose I have class ClassA with it’s own fields, methods and a static block.

 
public class ClassA {
 
 public ClassA(){
  System.out.println("Initializing ClassA");
 }
 // static blank final variable
 static final int i;
 static int b;
 //static block
 static {
  System.out.println("in static block");
  i = 5;
  b = i * 5;
  System.out.println("Values " + i + " " +  b);
 }
 public static int getB() {
  return b;
 }
 public static void setB(int b) {
  ClassA.b = b;
 }
 public static int getI() {
  return i;
 }
}

Another class, ClassB with a constructor, but it doesn’t refer to class A in anyway.

 
public class ClassB {
 
 public ClassB(){
  System.out.println("Initializing ClassB");
 }
}

Now you want to make sure that the static block should have executed before the initialization of ClassB bean.

If you define the beans in your XML configuration with out using depends-on attribute there is no guarantee that ClassA will be initialized first.

 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    
    <bean id="classB" class="org.netjs.prog.ClassB">
        
    </bean>
    
    <bean id="classA" class="org.netjs.prog.ClassA">
        
    </bean>
</beans>

You can run it using this test class -

 
import org.netjs.prog.ClassB;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {

 public static void main(String[] args) {
  ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml");
  ClassB cbObj = (ClassB)context.getBean("classB");
  //cbObj.displayValue();
  
  context.close();
 }

}

Output

Initializing ClassB
in static block
Values 5 25
Initializing ClassA

Here you can see ClassB object is initialized first and then ClassA object is initialized and its static block is executed.
But that is not what you want so you can use depends-on attribute to tell the spring framework that ClassA object should be ready before initializing ClassB object.

In that case your XML configuration would change -

 
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
    
    
    <bean id="classB" class="org.netjs.prog.ClassB" depends-on="classA">
        
    </bean>
    
    <bean id="classA" class="org.netjs.prog.ClassA">
        
    </bean>
</beans>

Now running it using the test class will yield -

in static block
Values 5 25
Initializing ClassA
Initializing ClassB

Now you can see that the ClassA is initialized first.

Dependency on multiple beans

To express a dependency on multiple beans, supply a list of bean names as the value of the depends-on attribute, with commas, whitespace and semicolons, used as valid delimiters:

<bean id="beanOne" class="ExampleBean" depends-on="manager,accountDao">
      <property name="manager" ref="manager" />
</bean>
<bean id="manager" class="ManagerBean" />
<bean id="accountDao" class="x.y.jdbc.JdbcAccountDao" />

Controlling shutdown order

Dependent beans that define a depends-on relationship with a given bean are destroyed first, prior to the given bean itself being destroyed. If you consider the above example, since ClassB bean is dependent on ClassA bean so ClassB bean will be destroyed first. But note that the destroy time dependency is specified in the case of singleton beans only.

That's all for this topic Using depends-on attribute Spring. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Dependency Injection using factory-method in Spring
  2. Wiring collections in Spring
  3. Run time injection using Spring Expression Language(SpEL)
  4. Bean definition inheritance in Spring
  5. How to inject prototype scoped bean in singleton bean

You may also like -

>>>Go to Spring tutorial page

Wednesday, 25 January 2017

Using util-namespace for wiring collection in Spring

Spring provides util-namespace that helps in dealing with common utility configuration issues, such as configuring collections, referencing constants. Mostly I use it for wiring collection and this post will show how to do that using util namespace.

To use the tags in the util schema, you need to declare the util-namespace and its schema in the XML:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util" 
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/springbeans.xsd
http://www.springframework.org/schema/util 
http://www.springframework.org/schema/util/springutil.xsd"> 
<!-- bean definitions here -->
</beans>

Using util:list and util:set

Let’s take an example class Order which has a list called itemList and set called itemSet.

Order class

public class Order {
    private String id;
    private List<String> itemList;
    private Set<String> itemSet;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public List<String> getItemList() {
        return itemList;
    }
    public void setItemList(List<String> itemList) {
        this.itemList = itemList;
    }
    public Set<String> getItemSet() {
        return itemSet;
    }
    public void setItemSet(Set<String> itemSet) {
        this.itemSet = itemSet;
    }   
}

In order to wire this list and set with in the order bean you can have property element like this -

<bean id="orderBean" class="org.netjs.exp.Spring_Example.Order">
        <property name="id" value = "1" />
        <property name="itemList">
            <list>
                <value>Laptop</value>
                <value>RAM</value>
                <value>Drive</value>
                <value>Drive</value>
            </list>
        </property>
        <property name="itemSet">
            <set>
                <value>Laptop</value>
                <value>RAM</value>
                <value>Drive</value>
                <value>Drive</value>
            </set>
            
        </property>
 </bean>

Using util:list (and util:set) you can create a separate bean for the list or set and then wire it as a reference in the required bean.

You can also explicitly control the exact type of List that will be instantiated and populated via the use of the list-class attribute on the <util:list/> element. For set the same attribute is called set-class.

XML configuration with util:list and util:set

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:util="http://www.springframework.org/schema/util" 
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/util 
    http://www.springframework.org/schema/util/spring-util.xsd">
    
    
    <util:list id="itemList" list-class="java.util.ArrayList">
        <value>Laptop</value>
        <value>RAM</value>
        <value>Drive</value>
        <value>Drive</value>
    </util:list>
    
    <util:set id="itemSet" set-class="java.util.TreeSet">
        <value>Laptop</value>
        <value>RAM</value>
        <value>Drive</value>
        <value>Drive</value>
    </util:set>
  
  <bean id="orderBean" class="org.netjs.exp.Spring_Example.Order">
      <property name="id" value = "1" />
      <property name="itemList" ref="itemList" />
      <property name="itemSet" ref="itemSet" />
  </bean>
  
</beans>

Output

item from List - Laptop
item from List - RAM
item from List - Drive
item from List - Drive
item from set - Drive
item from set - Laptop
item from set – RAM

Here you can see that list and set both are created as a separate beans now using util:list and util:set respectively. Also notice the use of list-class which is ArrayList and set-class which is given as TreeSet, that is why values in the set are sorted. Since Set can store only unique values “Drive” is stored only once even if it is specified twice for Set.

Using util:map and util:properties

In the example for util:map apart from Order class, Item class is also used.

Order class

Let’s say there is an Order class that has a Map and Properties fields.

import java.util.Map;
import java.util.Properties;

public class Order {
    private String id;
    private Map<String, Item> itemMap;
    private Properties itemProp;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public Map<String, Item> getItemMap() {
        return itemMap;
    }
    public void setItemMap(Map<String, Item> itemMap) {
        this.itemMap = itemMap;
    }
    public Properties getItemProp() {
        return itemProp;
    }
    public void setItemProp(Properties itemProp) {
        this.itemProp = itemProp;
    }  
}

Item Class

public class Item {
 private String name;
 private double price;
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public double getPrice() {
  return price;
 }
 public void setPrice(double price) {
  this.price = price;
 }
 
}

XML Configuration

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:util="http://www.springframework.org/schema/util" 
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/util 
    http://www.springframework.org/schema/util/spring-util.xsd">
    
    
    <util:map id="itemMap" key-type="java.lang.String" value-type="org.netjs.exp.Spring_Example.Item" map-class="java.util.HashMap">
         <entry key="1">
             <bean class="org.netjs.exp.Spring_Example.Item" p:name="RAM" p:price="34.78" />
         </entry>
          <entry key="2">
             <bean class="org.netjs.exp.Spring_Example.Item" p:name="Laptop" p:price="534.00" />
         </entry>
    </util:map>
    
    <util:properties id="itemProperties" value-type="java.lang.String">
        <prop key="Laptop">500</prop>
        <prop key="RAM">56.89</prop>
    </util:properties>
    

  
  <bean id="orderBean" class="org.netjs.exp.Spring_Example.Order">
      <property name="id" value = "1" />
      <property name="itemMap" ref="itemMap" />
      <property name="itemProp" ref="itemProperties" />
  </bean>
  
</beans>

Output

item from Map - 1 RAM 34.78
item from Map - 2 Laptop 534.0
items from Properties {Laptop=500, RAM=56.89}

Here you can notice how map and properties are configured using util:map and util:properties respectively. In util:map notice the use of map:class attribute to define the type of Map used, key-type and value-type attributes are also used to define the type of map keys and values. While defining the values of Map, which are of type Item, p-namespace is used.

That's all for this topic Using util-namespace for wiring collection in Spring. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Using c-namespace in Spring
  2. What is Dependency Injection in Spring
  3. Spring example program using automatic configuration
  4. Difference between component-scan and annotation-config in Spring
  5. Select query using NamedParameterJDBCTemplate in Spring framework

You may also like -

>>>Go to Spring tutorial page

Monday, 23 January 2017

Using c-namespace in Spring

If you have worked on Spring and used XML configuration for wiring beans you would have used <constructor-arg> element several times for providing, property values and/or providing reference for beans, as a constructor injection. If you are looking for any shorter alternative, just as p-namesapce is used in place of nested <property> element, you can use c-namespace.

The c-namespace enables you to use the bean element’s attributes for configuring the constructor arguments rather than nested constructor-arg elements.

As example –

If you have an XML configuration for bean employee which has a constructor that refers to the bean of type address with constructor-arg you will write it like this -

<bean id="employee" class="org.netjs.model.Employee">
    <constructor-arg ref="address"/>
</bean>

You can use c-namespace to shorten it like this -

<bean id="employee" class="org.netjs.model.Employee" c:officeAddress-ref="address">
    <!-- <constructor-arg ref="address"/> -->
</bean>

You can see here that instead of using nested <constructor-arg> element you can use bean element’s attribute itself.

In this way of using c-namespace for injection of bean reference c:officeAddress-ref="address", c: denotes the use of c-namespace, officeAddress is the constructor argument name with in the employee class where value is injected, -ref indicates injection of bean reference.

For literals

Same way c-namespace can be used for injecting literal values.

As example

If you have an XML configuration for bean employee which has a constructor argument empName then you can provide a literal value to empName property like this –

<bean id="employee" class="org.netjs.model.Employee">
    <constructor-arg value="Ram"/>
</bean>

Using c-namespace you can shorten it like this –

<bean id="employee" class="org.netjs.model.Employee" c:empName="Ram">
    <!-- <constructor-arg value="Ram"/> -->
</bean>

Full example

As we have already seen there are two classes Address and Employee and Address class bean is referred in Employee.

Employee class

public class Employee {
 private int empId;
 private String empName;
 private int age;
 private Address officeAddress;
 
 public Employee(int empId, String empName, int age, Address officeAddress){
  this.empId = empId;
  this.empName = empName;
  this.age = age;
  this.officeAddress = officeAddress;
 }
 
 public Address getOfficeAddress() {
  return officeAddress;
 }
 
 public int getEmpId() {
  return empId;
 }
 
 public String getEmpName() {
  return empName;
 }
 
 public int getAge() {
  return age;
 }
}

Here it can be seen that Employee class has constructor that has some literal values as argument and one argument of type Address.

Address Class

public class Address {
 private String number; 
 private String street; 
 private String city; 
 private String state; 
 private String pinCode; 
 public String getNumber() {
  return number;
 }
 public void setNumber(String number) {
  this.number = number;
 }
 public String getStreet() {
  return street;
 }
 public void setStreet(String street) {
  this.street = street;
 }
 public String getCity() {
  return city;
 }
 public void setCity(String city) {
  this.city = city;
 }
 public String getState() {
  return state;
 }
 public void setState(String state) {
  this.state = state;
 }
 public String getPinCode() {
  return pinCode;
 }
 
 public void setPinCode(String pinCode) {
  this.pinCode = pinCode;
 }
 
}

XML Configuration

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:c="http://www.springframework.org/schema/c"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context.xsd">
   
    
    <bean id="address" class="org.netjs.model.Address" p:number="101" p:street="M I Road" 
            p:city="Jaipur" p:state="Rajasthan" p:pinCode="302001"> 
    </bean>
    
    <bean id="employee" class="org.netjs.model.Employee" c:empId="1001" c:age="25" c:empName="Ram" c:officeAddress-ref="address" />
    
</beans>
Here notice the inclusion of xmlns:c="http://www.springframework.org/schema/c” and xmlns:p="http://www.springframework.org/schema/p” in XML configuration for c-namespace and p-namespace respectively.

In bean definition for address p-namespace is used for providing values. In bean definition for Employee c-namespace is used to provide values for constructor arguments.

Test Class

You can run this code using the following code -

import org.netjs.model.Address;
import org.netjs.model.Employee;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {

    public static void main(String[] args) {
        
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml");
        Employee emp = (Employee)context.getBean("employee");  
        Address addr = emp.getOfficeAddress();
        System.out.println("name " + emp.getEmpName());
        System.out.println("City " + addr.getCity());
        System.out.println("PinCode " + addr.getPinCode());
        context.close();    
    }

}

Output

name Ram
City Jaipur
PinCode 302001 

That's all for this topic Using c-namespace in Spring. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. What is Dependency Injection in Spring
  2. Using p-namespace for shorter XML in Spring
  3. Injecting inner bean in Spring
  4. Select query using JDBCTemplate in Spring framework
  5. Using Conditional annotation in Spring framework

You may also like -

>>>Go to Spring tutorial page

Wednesday, 18 January 2017

Spliterator in Java

Spliterators, like iterators, are for traversing the elements of a source. The source of elements covered by a Spliterator could be, for example, an array, a Collection, an IO channel, or a generator function.

As the name suggests, spliterator can split the source and iterate the splitted parts in parallel. That way a huge data source can be divided into small sized units that can be traversed and processed parallely.

Spliterator interface

Spliterator is a generic interface in Java defined as -

Interface Spliterator<T>

Where T is the type of elements returned by this Spliterator.

Spliterator methods

Though spliterator will increase performance by traversing the collection in parallel but you can also use spliterator even if you are not using parallel execution.

If you use iterator you have to use two methods hasNext() to ensure that there is next element and then next() method to use that element. Spliterator provides methods that combines these two methods into one and making it more convenient to use.

Some of the frequently used methods of Spliterator are -

  • tryAdvance() - If a remaining element exists, performs the given action on it, returning true; else returns false. Its form is -
    tryAdvance(Consumer<? super T> action)
    
    Here action is an instance of Consumer, which is a functional interface, it specifies the function that has to be applied on the next element while traversing the collection (or any other source).
  • forEachRemaining - Performs the given action for each remaining element, sequentially in the current thread, until all elements have been processed or the action throws an exception. Its form is -
    default void forEachRemaining(Consumer<? super T> action)
    
  • estimateSize() - Returns an estimate of the number of elements that would be encountered by forEachRemaining traversal, or returns Long.MAX_VALUE if infinite, unknown, or too expensive to compute. Its form is -
    long estimateSize()
    
  • trySplit() - If current spliterator can be partitioned a new spliterator is created, it partitions the elements of the source so that new spliterator traverse one of the partition while original spliterator traverses the other partition.
  • characteristics() - Returns a set of characteristics of this Spliterator and its elements.

Spliterator characteristics

A Spliterator also reports a set of characteristics() of its structure, source, and elements from among ORDERED, DISTINCT, SORTED, SIZED, NONNULL, IMMUTABLE, CONCURRENT, and SUBSIZED.

These characteristics are defined as constant fields in the Spliterator interface.

Read more about them here - https://docs.oracle.com/javase/8/docs/api/java/util/Spliterator.html#characteristics--

To see constant values - https://docs.oracle.com/javase/8/docs/api/constant-values.html#java.util.Spliterator

Using characteristics() method will give you a result represented as ORed values of the characterstics relevant for the given source.

Spliterator example code

If you have a list of names and you want to iterate it and print the names, using iterator it can be done like -

public class IteratorDemo {

    public static void main(String[] args) {
        List<String> nameList = Arrays.asList("Ram", "Sheila", "Mukesh", "Rani", "Nick", "Amy", "Desi", "Margo");
        Iterator<String> itr = nameList.iterator();
        while (itr.hasNext()) {
            System.out.println("name - " + itr.next());   
        }
    }
}

Same thing can be done using spliterator like this -

public class SpliteratorDemo {

    public static void main(String[] args) {
        List<String> nameList = Arrays.asList("Ram", "Sheila", "Mukesh", "Rani", "Nick", "Amy", "Desi", "Margo");
        Spliterator<String> splitStr = nameList.spliterator();
        while(splitStr.tryAdvance((n) -> System.out.println("name - " + n)));
    }

}

Here you can see you need to use only one method tryAdvance() which combines both hasNext() and next() methods of the iterator.

Using forEachRemaining

If you want to convert all the names to lowercase you can use forEachRemaining method.

import java.util.Arrays;
import java.util.List;
import java.util.Spliterator;

public class SpliteratorDemo {

    public static void main(String[] args) {
        List<String> nameList = Arrays.asList("Ram", "Sheila", "Mukesh", "Rani", "Nick", "Amy", "Desi", "Margo");
        Spliterator<String> splitStr = nameList.spliterator();
        splitStr.forEachRemaining( 
            (n) -> {
                String x = n.toLowerCase();
                System.out.println("" + x);
            }
        );
    }

}

Using trySplit

If you want to split the original spliterator so that you can traverse the element parallely.

import java.util.Arrays;
import java.util.List;
import java.util.Spliterator;

public class SpliteratorDemo {

    public static void main(String[] args) {
        List<String> nameList = Arrays.asList("Ram", "Sheila", "Mukesh", "Rani", "Nick", "Amy", "Desi", "Margo");
        Spliterator<String> splitStr = nameList.spliterator();
        Spliterator<String> splitStr2 = splitStr.trySplit();
        // Check if splitting actually happened, then use it
        if(splitStr2 != null){
            System.out.println("Spliterator-2");
            while(splitStr2.tryAdvance((n) -> System.out.println("name - " + n)));
        }
        // Original spliterator
        System.out.println("Original Spliterator");
        while(splitStr.tryAdvance((n) -> System.out.println("name - " + n)));
    }
        
}

Output

Spliterator-2
name - Ram
name - Sheila
name - Mukesh
name - Rani
Original Spliterator
name - Nick
name - Amy
name - Desi
name - Margo

Here you are splitting the spliterator make sure to check that splitting actually happened by checking for null.

Here note one thing, according to Java docs -

If the original thread hands a spliterator off to another thread for processing, it is best if that handoff occurs before any elements are consumed with tryAdvance(), as certain guarantees (such as the accuracy of estimateSize() for SIZED spliterators) are only valid before traversal has begun.

So make sure you first do the splitting then only start any operation on the elements.

You can split a spliterator into many partitions, if it can’t be split further null would be returned.

See an example here -

 static <T> void parEach(TaggedArray<T> a, Consumer<T> action) {
   Spliterator<T> s = a.spliterator();
   long targetBatchSize = s.estimateSize() / (ForkJoinPool.getCommonPoolParallelism() * 8);
   new ParEach(null, s, action, targetBatchSize).invoke();
 }

 static class ParEach<T> extends CountedCompleter<Void> {
   final Spliterator<T> spliterator;
   final Consumer<T> action;
   final long targetBatchSize;

   ParEach(ParEach<T> parent, Spliterator<T> spliterator,
           Consumer<T> action, long targetBatchSize) {
     super(parent);
     this.spliterator = spliterator; this.action = action;
     this.targetBatchSize = targetBatchSize;
   }

   public void compute() {
     Spliterator<T> sub;
     while (spliterator.estimateSize() > targetBatchSize &&
            (sub = spliterator.trySplit()) != null) {
       addToPendingCount(1);
       new ParEach<>(this, sub, action, targetBatchSize).fork();
     }
     spliterator.forEachRemaining(action);
     propagateCompletion();
   }
 }

That's all for this topic Spliterator in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!

Referrence - https://docs.oracle.com/javase/8/docs/api/java/util/Spliterator.html


Related Topics

  1. Stream API in Java 8
  2. Java Stream API Examples
  3. Primitive type streams in Java Stream API
  4. Collecting in Java Stream API
  5. Lambda expressions in Java 8

You may also like -

>>>Go to Java advance topics page

Monday, 16 January 2017

FlatMap in Java

If you know about the mapping operation in Java stream, in mapping operation the given function is applied to all the elements of the stream.

Where as flattening a structure, in simple terms, means bringing all the nested structures at the same level. If you have a data structure with many nested levels flattening will break all the nested levels and bring all the elements at the same level.

As example if you have a list of Strings, list<String> like - [[“a”, “b”, “c”], [“c”, “d”], [“c”, “e”, “f”]] then flattening it will bring everything to the same level and the structure you will have be like this -

[“a”, “b”, “c”, “c”, “d”, “c”, “e”, “f”].

Bringing them both together in a method flatMap() means, function will be applied to all the elements of the stream and then it will be flatten to have a single level structure.

FlatMap example

Let’s say there is a class called Order which has a collection of items. If you have a stream of orders you can get a stream containing all the items in all the orders like this -

Order class

public class Order {
    private String orderId;
    private List<String> items;
    public String getOrderId() {
        return orderId;
    }
    public void setOrderId(String orderId) {
        this.orderId = orderId;
    }
    public List<String> getItems() {
        return items;
    }
    public void setItems(List<String> items) {
        this.items = items;
    }
}

Getting a stream containing all the items in all the orders

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class FlatMapDemo {

    public static void main(String[] args) {
        List<Order> orderList = getOrderList();
        Stream<String> item = orderList.stream().flatMap(order -> order.getItems().stream());
        item.forEach(System.out::println);
    }
    
    /**
     * 
     * @return
     */
    private static List<Order> getOrderList(){
        List<Order> orderList = new ArrayList<Order>();
        Order order = new Order();
        order.setOrderId("1");
        order.setItems(Arrays.asList("Item1", "Item2", "Item3"));
        orderList.add(order);
        order = new Order();
        order.setOrderId("2");
        order.setItems(Arrays.asList("Item3", "Item5"));
        orderList.add(order);
        return orderList;
    }
}

Output

Item1
Item2
Item3
Item3
Item5

Here you can see using flatMap() you are getting all the items which are stored as a list inside orders.

Methods for primitive data types

In Java stream API there are variants of flatMap method which work with primitive data types. These methods are -

  • flatMapToInt() - Works with int data type. Returns a new IntStream.
  • flatMapToLong() - Works with long data type. Returns a new LongStream.
  • flatMapToDouble() - Works with double data type. Returns a new DoubleStream.

flatMapToInt example

If you have 2D array and you want to flatten it and get a new IntStream you can get it like this -

int[][] numArray = {{1, 2}, {3, 4}, {5, 6}};
Stream<int[]> numStream = Stream.of(numArray);
IntStream iStream = Stream.of(numArray).flatMapToInt(n -> Arrays.stream(n));
iStream.forEach(System.out::println);

Output

1
2
3
4
5
6

In the lambda expression n -> Arrays.stream(n), n denotes one of the array with in the 2D array, so first time {1,2} will be passed as the mapped stream and its contents will be placed in the new IntStream, next time another array {3,4} will be passed and so on.

That's all for this topic FlatMap in Java. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Collecting in Java Stream API
  2. Reduction Operations in Java Stream API
  3. Parallel Stream in Java Stream API
  4. Java Stream API Examples
  5. Primitive type streams in Java Stream API
  6. Method reference in Java 8

You may also like -

>>>Go to Java advance topics page

Friday, 13 January 2017

Collecting in Java Stream API

Collect method is used to perform a mutable reduction operation on the element of the given stream.

A mutable reduction operation can be defined as an operation that accumulates input elements into a mutable result container, such as a Collection or StringBuilder, as it processes the elements in the stream. In simple way you can say collect methods are used to get a collection from the stream.

Note that this is a terminal operation.

collect method

There are two variants of collect() method -

  1. <R,A> R collect(Collector<? super T,A,R> collector) - Performs a mutable reduction operation on the elements of this stream using a Collector.
    • R - the type of the result
    • A - the intermediate accumulation type of the Collector
    • T – Element type of the stream
    • collector – Instance of the Collector interface

    Collector interface

    public interface Collector<T,A,R>
    

    A Collector is specified by four functions that work together to accumulate entries into a mutable result container, and optionally perform a final transform on the result. They are:

    • creation of a new result container (supplier())
    • incorporating a new data element into a result container (accumulator())
    • combining two result containers into one (combiner())
    • performing an optional final transform on the container (finisher())

    Collectors Class

    Collector class, an implementation of Collector interface implements various useful reduction operations (as static methods), such as accumulating elements into collections, summarizing elements according to various criteria, etc.

    These are the methods you will generally use rather than implementing Collector interface yourself.

    Examples using the predefined collectors

    For these examples Employee class will be used -

    Employee class

    class Employee {
        private String empId;
        private int age;
        private String name;
     private char sex;
        private int salary;
     Employee(String empId, int age, String name, char sex, int salary){
      this.empId = empId;
      this.age = age;
      this.name = name;
      this.sex = sex;
      this.salary = salary;
     }
     public String getEmpId() {
      return empId;
     }
     public void setEmpId(String empId) {
      this.empId = empId;
     }
     public int getAge() {
      return age;
     }
     public void setAge(int age) {
      this.age = age;
     }
     public String getName() {
      return name;
     }
     public void setName(String name) {
      this.name = name;
     }
     public char getSex() {
      return sex;
     }
     public void setSex(char sex) {
      this.sex = sex;
     }
     public int getSalary() {
      return salary;
     }
     public void setSalary(int salary) {
      this.salary = salary;
     } 
    }
    
    1. If you want a list having names of all the employees you can use the toList method of the Collectors class.

      List<String> nameList = empList.stream().map(Employee::getName).collect(Collectors.toList());
      
    2. If you want to store the names in the set.
      Set<String> nameSet = empList.stream().map(Employee::getName).collect(Collectors.toSet());
      
    3. If you want to specify the collection yourself, as example you want the name to be stored in sorted order and want to use TreeSet for the purpose.
      Set<String> nameSet = empList.stream().map(Employee::getName).collect(Collectors.toCollection(TreeSet::new));
      
    4. If you want to store data in a Map so that empId is the key and name is the value.
      Map<String, String> nameMap = empList.stream().collect(Collectors.toMap(Employee::getEmpId, Employee::getName));
      
    5. If you want all the names as a String, joined by comma
      String names = empList.stream().map(Employee::getName).collect(Collectors.joining(","));
      
    6. If you want total salary given to all the employees -
      int totalSalary = empList.stream().collect(Collectors.summingInt(Employee::getSalary));
      
    7. If you want to group the employees by sex -
      Map<Character, List<Employee>> empMap = empList.stream().collect(Collectors.groupingBy(Employee::getSex));
      
      There is also a groupingByConcurrent method which should be used with parallelStream, see example here Parallel Stream in Java Stream API.
    8. In case function is a Predicate, i.e. returns a boolean-valued function it is more efficient to use partitioningBy rather than groupingBy. As Example if you want to partition by employees getting salary greater than or equal to 8000.
      Map<Boolean, List<Employee>> empMap = empList.stream().collect(Collectors.partitioningBy(e -> e.getSalary() >= 8000 ));
      

    There are also methods like summarizingInt, summarizingDouble and summarizingLong that provide summary statistics, see an example in Java stram example.

  2. Another variation of the collect method -
    <R> R collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner)
    
    • supplier - a function that creates a new result container.
    • accumulator - function for adding an element into a result.
    • combiner - function for combining two partial result.

    As example – If you want to accumulate strings into an ArrayList -

    List<String> asList = Stream.of("a", "b", "c").collect(ArrayList::new, 
    ArrayList::add, ArrayList::addAll);
    
    If you prefer using lambda expressions instead of method reference then you can write the same thing as -
    asList = Stream.of("a", "b", "c").collect(() -> new ArrayList<>(), (alist, word) -> alist.add(word), (alist1, alist2) -> alist1.addAll(alist2));
    

    Here you can see first param is creating a new result container (a new ArrayList), second param is a function for adding element to the result and third is combining two partial results.

That's all for this topic Collecting in Java Stream API. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Stream API in Java 8
  2. Reduction Operations in Java Stream API
  3. Parallel Stream in Java Stream API
  4. Map operation in Java Stream API
  5. Lambda expressions in Java 8

You may also like -

>>>Go to Java advance topics page

Wednesday, 11 January 2017

Map operation in Java Stream API

Map operations, as the name suggests, are used to do the element mapping from one stream to another. Map operation will return a stream consisting of the results of applying the given function to the elements of this stream. So, whatever function is provided is applied on all the elements of the stream.

One thing to note here is; since new stream is returned map operation is an intermediate operation.

map method

Java stream API provides a map method -

<R> Stream<R> map(Function<? super T,? extends R> mapper) - Returns a stream consisting of the results of applying the given function to the elements of this stream.

Here R is the element type of the new stream, T denotes the element type of the existing stream and mapper is the function which will be applied to all the elements of the stream.

Here note that mapper is an instance of Function which is a functional interface. Since it is a functional interface therefore it can be used as the assignment target for a lambda expression or method reference.

Mapping examples in Java Stream

  1. You have a stream of some names and you want to get a list where names are stored in upper case. In that case using map() method you can apply a function to all the elements of the stream to convert those elements to upper case and then using collector, collect them in a list.
    public class MappingDemo {
    
        public static void main(String[] args) {
            List<String> nameList = Stream.of("amy", "nick", "margo", "desi")
                  .map(s->s.toUpperCase()).collect(Collectors.toList());
            System.out.println("Names in upper case" + nameList);
    
        }
    
    }
    

    Output

    Names in upper case[AMY, NICK, MARGO, DESI]
    
  2. You have a list of salaries and you want to increase salaries by 10%.
    List<Integer> myList = Arrays.asList(7000, 5000, 4000, 24000, 17000, 6000);  
    myList.stream().map(i -> (i+ (i * 10/100))).forEach(System.out::println);
    

    Output

    7700
    5500
    4400
    26400
    18700
    6600
    
  3. There is an employee class and you want the name of all the female employees.
    public class MappingDemo {
    
        public static void main(String[] args) {
            MappingDemo md = new MappingDemo();
            List<Employee> empList = md.createList();
            System.out.println("--- Name of female employees ---");
            empList.stream().filter(e -> (e.getSex() == 'F'))
                       .map(e -> e.getName()).forEach(System.out::println);
    
        }
        
        // Stub method to create list of employee objects
        private List<Employee> createList(){
            List<Employee> empList = Arrays.asList(new Employee("E001", 40, "Ram", 'M', 5000), 
                                           new Employee("E002", 35, "Sheila", 'F', 7000), 
                                           new Employee("E003", 24, "Mukesh", 'M', 9000), 
                                           new Employee("E004", 37, "Rani", 'F', 10000));
            
            return empList;
        }
        class Employee {
            private String empId;
            private int age;
            private String name;
            private char sex;
            private int salary;
            Employee(String empId, int age, String name, char sex, int salary){
                this.empId = empId;
                this.age = age;
                this.name = name;
                this.sex = sex;
                this.salary = salary;
            }
            public String getEmpId() {
                return empId;
            }
            public void setEmpId(String empId) {
                this.empId = empId;
            }
            public int getAge() {
                return age;
            }
            public void setAge(int age) {
                this.age = age;
            }
            public String getName() {
                return name;
            }
            public void setName(String name) {
                this.name = name;
            }
            public char getSex() {
                return sex;
            }
            public void setSex(char sex) {
                this.sex = sex;
            }
            public int getSalary() {
                return salary;
            }
            public void setSalary(int salary) {
                this.salary = salary;
            } 
            
        }
    
    }
    

    Output

    --- Name of female employees ---
    Sheila
    Rani
    

Variants of map() method

There are three variants of map() method which return a primitive stream.

  • mapToInt(ToIntFunction<? super T> mapper) - Returns an IntStream consisting of the results of applying the given function to the elements of this stream.
  • mapToDouble(ToDoubleFunction<? super T> mapper) - Returns a DoubleStream consisting of the results of applying the given function to the elements of this stream.
  • mapToLong(ToLongFunction<? super T> mapper) - Returns a LongStream consisting of the results of applying the given function to the elements of this stream.

Apart from that, in all the primitive type streams – IntStream, LongStream and Double Stream there is also a mapToObj() method.

For IntStream mapToObj() function os defined like this -

  • mapToObj(IntFunction<? extends U> mapper) - Returns an object-valued Stream consisting of the results of applying the given function to the elements of this stream.

Code examples

  1. If you want to get the total of salaries for the employees (Using the employee class as above) -
    int totalSalary = empList.stream().mapToInt(e -> e.getSalary()).sum();
    System.out.println("total of salaries " + totalSalary);
    

    Output

    total of salaries 31000
    
  2. If you want to get the maximum salary -
    OptionalInt maxSalary = empList.stream().mapToInt(e -> e.getSalary()).max();
    if(maxSalary.isPresent()){
        System.out.println("Maximum Salary " + maxSalary.getAsInt());
    }
    

    Output

    Maximum Salary 10000
    
  3. For your testing you want to create 500 objects of some class -
    List<Employee> empList = IntStream.rangeClosed(1, 500).mapToObj(Employee::new).collect(Collectors.toList());
    

That's all for this topic Map operation in Java Stream API. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Stream API in Java 8
  2. Parallel Stream in Java Stream API
  3. Java Stream API Examples
  4. Reduction Operations in Java Stream API
  5. Lambda expressions in Java 8

You may also like -

>>>Go to Java advance topics page

Monday, 9 January 2017

Primitive type streams in Java Stream API

If you have gone through the post Stream API in Java 8 one thing you would have noticed is that Streams work on object references. They can’t work on primitive types because of that many times people use Stream<Integer>, Stream<Long> or Stream<Double> in order to wrap primitive types into a wrapper object.

In Java Stream API Examples you will see an example where integers are collected in Stream<Integer>. But, that is not an efficient way to work with primitive types as you need to wrap them into wrapper objects. Instead you should use primitive specializations of Stream like IntStream, LongStream, and DoubleStream that can store primitive values.

Apart from int you can use IntStream for short, char, byte, and boolean. For float DoubleStream can be used.

Creating primitive type Streams

  1. You can use of() method to create primitive type Stream. It has two variants, for IntStream these two variants are -
    • static IntStream of(int t) - Returns a sequential IntStream containing a single element.
    • static IntStream of(int... values) - Returns a sequential ordered stream whose elements are the specified values.

    As Example -

    System.out.println("--- IntStream ---");
    IntStream is = IntStream.of(3, 4, 5, 6);
    is.forEach(System.out::println);
    

    Output

    --- IntStream ---
    3
    4
    5
    6
    

    It works the same way for LongStream and DoubleStream.

  2. Using Arrays.stream() method

    It has two variants. For DoubleStream these two variants are -

    • public static DoubleStream stream(double[] array) - Returns a sequential DoubleStream with the specified array as its source.
    • public static DoubleStream stream(double[] array, int startInclusive, int endExclusive) - Returns a sequential DoubleStream with the specified range of the specified array as its source.

    It works the same way for IntStream and LongStream.

    Example of Arrays.stream()

    System.out.println("--- DoubleStream ---");
    double[] num = {3.0, 4.7, 5.2, 6.8};
    DoubleStream numStream = Arrays.stream(num);
    numStream.forEach(System.out::println);
    System.out.println("--- With Specified range ---");
    numStream = Arrays.stream(num, 0, 2);
    numStream.forEach(System.out::println);
    

    Output

    --- DoubleStream ---
    3.0
    4.7
    5.2
    6.8
    --- With Specified range ---
    3.0
    4.7
    

    In the second variant since second argument is 2 and the end index passed is exclusive so effective range for the stream is 0 – 1.

  3. Using range() and rangeClosed() methods
    • static IntStream range(int startInclusive, int endExclusive) - Returns a sequential ordered IntStream from startInclusive (inclusive) to endExclusive (exclusive) by an incremental step of 1.
    • static IntStream rangeClosed(int startInclusive, int endInclusive) - Returns a sequential ordered IntStream from startInclusive (inclusive) to endInclusive (inclusive) by an incremental step of 1.

    It works the same way for LongStream. Note that these methods will work with IntStream and LongStream, not provided for DoubleStream.

    As example – If you want a stream with 1000 integers, 1 – 1000.

    IntStream thousandInt = IntStream.rangeClosed(1, 1000);
    

    Since you can create a range of numbers, these methods help with testing with large data. See an example in Parallel Stream in Java Stream API.

Transforming Stream to primitive type Stream

Stream interface provides methods mapToInt, mapToDouble and mapToLong that can be used to transform stream of objects to a stream of primitive types.

Infact reduction operations such as average, sum, min (without specifying a comparator), max (without specifying a comparator) are not provided for Stream with object references. Since these operations are used quite frequently with streams so you will do this transformation using mapToxxx methods a lot if time.

As example – If you have a list of employee objects and you want to get the maximum salary you can do it using mapToInt method like this -

OptionalInt maxSalary = empList.parallelStream().mapToInt(e -> e.getSalary()).max();

If you want total amount given to all employees then you can sum the salaries like this -

int totalSalary = empList.parallelStream().mapToInt(e -> e.getSalary()).sum();

If you have noticed the first example returns the result of type OptionalInt. Methods that return result of type Optional in Stream with objects will return result of type OptionalInt, OptionalLong and OptionalDouble. In these classes there are specific methods like getAsInt(), getAsLong() and getAsDouble() rather than a generic get() method present in Optional class.

Transforming primitive type Stream to Stream of objects

All the primitive type Streams have boxed() method that will return a Stream consisting of the elements of this stream wrapped as object.

Thus used with DoubleStream, boxed() method will return a Stream consisting of the elements of this stream, each boxed to a Double i.e. Stream<Double>.

Same way for IntStream and LongStream you will get a Stream having elements of type Integer and Long respectively, i.e. Stream<Integer> and Stream<Long>.

As example -

Stream<Integer> iStream = IntStream.of(3, 4, 5, 6).boxed();

That's all for this topic Primitive type streams in Java Stream API. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Stream API in Java 8
  2. Reduction Operations in Java Stream API
  3. Lambda expressions in Java 8
  4. Method reference in Java 8
  5. Functional interface annotation in Java 8

You may also like -

>>>Go to Java advance topics page

Wednesday, 4 January 2017

Parallel Stream in Java Stream API

You can execute streams in serial or in parallel. When a stream executes in parallel, the Java runtime partitions the stream into multiple sub-streams. Aggregate operations iterate over and process these sub-streams in parallel and then combine the results.

This parallel execution of data, with each sub-stream running in a separate thread, will result in increase in performance. Since, part of the data (sub-stream) is processed by different processors of multi-core processors in separate threads which are later combined to give the final result, bulk operations can also be processed in less time making the whole process more efficient and less time consuming.

Since partial results are computed by separate threads and later combined so it becomes important to think about these points -

  1. Is separate combiner needed to combine partial results or aggregate function itself can work as combiner too.
  2. Since multi-threading is involved so any shared variable should not be updated by any operation in the parallel stream.
  3. Most of the time collection is used as a data source of the stream and collections are not thread safe. Which means that multiple threads cannot manipulate a collection without introducing thread interference errors.
  4. Parallel stream uses common fork-join thread pool. Thus, running a performance intensive long running task may block all threads in the pool, which may block all other tasks (as no threads will be available) that are using parallel streams.
  5. Note that parallelism is not automatically faster than performing operations serially, although it can be if you have enough data and processor cores. While aggregate operations enable you to more easily implement parallelism, it is still your responsibility to determine if your application is suitable for parallelism.

How to get a parallel stream

Collection has methods Collection.stream() and Collection.parallelStream(), which produce sequential and parallel streams respectively.

You can also call parallel() method on a sequential stream to get a parallel stream. The parallel() method is defined in the BaseStream interface.

As example: If you have an Employee class and for some testing you want to create 1000 objects of Employee class then you can use parallel() method with range -

List<Employee> empList = IntStream.rangeClosed(1, 1000).parallel().mapToObj(Employee::new).collect(Collectors.toList());

Examples using parallel stream

Let’s first see a simple example using parallel stream where you need to find the employee with maximum salary.

Employee class

public class Employee {
    private String lastName;
    private String firstName;
    private String empId;
    private int age;
    private int salary;
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getEmpId() {
        return empId;
    }
    public void setEmpId(String empId) {
        this.empId = empId;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    
    public String getFullName(){
     return this.firstName + " " + this.lastName;
    }
   
    public int getSalary() {
 return salary;
    }
    public void setSalary(int salary) {
 this.salary = salary;
    }
}

Using parallel stream

import java.util.ArrayList;
import java.util.List;
import java.util.OptionalInt;

public class ParallelDemo1 {

    public static void main(String[] args) {
        // getting list of employee 
        List<Employee> empList = createList();
        OptionalInt maxSalary = empList.parallelStream().mapToInt(e -> e.getSalary()).max();
        if(maxSalary.isPresent()){
            System.out.println("Max Salary " + maxSalary.getAsInt());
        }
    }
    
    // Stub method to create list of employee objects
    private static List createList(){
        List<Employee> empList = new ArrayList<Employee>();
        Employee emp = new Employee();
        emp.setEmpId("E001");
        emp.setAge(40);
        emp.setFirstName("Ram");
        emp.setLastName("Chandra");
        emp.setSalary(5000);
        empList.add(emp);
        emp = new Employee();
        emp.setEmpId("E002");
        emp.setAge(35);
        emp.setFirstName("Sheila");
        emp.setLastName("Baijal");
        emp.setSalary(7000);
        empList.add(emp);
        emp = new Employee();
        emp.setEmpId("E003");
        emp.setAge(24);
        emp.setFirstName("Mukesh");
        emp.setLastName("Rishi");
        emp.setSalary(9000);
        empList.add(emp);
        emp = new Employee();
        emp.setEmpId("E004");
        emp.setAge(37);
        emp.setFirstName("Rani");
        emp.setLastName("Mukherjee");
        emp.setSalary(10000);
        empList.add(emp);
        return empList;
    }
}

Output

Max Salary 10000

Mistake of updating a shared variable

As already stated above updating a shared state when using parallel stream may cause problem due to multi-threading. Let’s see it with an example.

There is an Employee class and 500 objects of the Employee class are stored in a list. Then using parallel stream you are trying to get the total salary paid to all employees.

Employee class

Employee class is same as used above with one difference, now there is a constructor with int argument which is used to set salary property. Using range method 500 objects will be created with salary set as 1..500.

public class Employee {
    private String lastName;
    private String firstName;
    private String empId;
    private int age;
    private int salary;
    
    Employee(int salary){
     this.salary = salary;
    }
    
    public String getLastName() {
        return lastName;
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
    public String getFirstName() {
        return firstName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
    public String getEmpId() {
        return empId;
    }
    public void setEmpId(String empId) {
        this.empId = empId;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    
    public String getFullName(){
     return this.firstName + " " + this.lastName;
    }
   
    public int getSalary() {
  return salary;
    }
}

Total Salary Calculation

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class ParallelDemo {

    public static void main(String[] args) {
        Salary sal = new Salary();
        List<Employee> empList = createList();
        empList.parallelStream().forEach(sal::doProcess);
        
        System.out.println("Total - " + sal.getTotalSalary());

    }
    // Stub method to create list of employee objects
    private static List createList(){
        List<Employee> empList = IntStream.rangeClosed(1, 500).mapToObj(Employee::new).collect(Collectors.toList());
        return empList;
    }
}

class Salary{
    private int total = 0;
    
    public void doProcess(Employee emp){
        addSalary(emp.getSalary());
    }
    
    public void addSalary(int salary){
        total = total + salary;
    }
    public int getTotalSalary(){
        return total;
    }
}

Output

Total – 113359, Total – 125250, Total – 120901, Total – 123835, Total – 125250

I got these 5 outputs on executing it 5 times. You can see that output is different (Correct output is 125250 by the way). It is because total is changed from the parallel stream which is a shared variable.

If you have seen the first example I have given for parallel stream you must have got an idea what’s the better way to do it.

public class ParallelDemo {

    public static void main(String[] args) {
        Salary sal = new Salary();
        List<Employee> empList = createList();
        //empList.parallelStream().forEach(sal::doProcess);
        int totalSalary = empList.parallelStream().mapToInt(e -> e.getSalary()).sum();
        sal.addSalary(totalSalary);
        System.out.println("Total - " + sal.getTotalSalary());

    }
    // Stub method to create list of employee objects
    private static List createList(){
        List<Employee> empList = IntStream.rangeClosed(1, 500).mapToObj(Employee::new).collect(Collectors.toList());
        return empList;
    }
}

Here note that you are not changing the shared variable in the stream. You are getting the salaries of the employees and summing it. That way, even in parallel stream there is no problem as different threads are getting different data to add and then those partial results are combined to get the total salary.

Using Collectors.groupingByConcurrent

Operation groupingBy performs poorly with parallel streams. (This is because it operates by merging two maps by key, which is computationally expensive). With parallel stream you should use groupingByConcurrent operation instead of groupingBy which returns an instance of ConcurrentMap instead of Map.

As example – If you have an Employee class and you want to group employees on the basis of sex it can be done as -

import java.util.Arrays;
import java.util.List;

import java.util.concurrent.ConcurrentMap;
import java.util.stream.Collectors;

public class ParallelDemo1 {

    public static void main(String[] args) {
        ParallelDemo1 pd = new ParallelDemo1();
        // getting list of employee 
        List<Employee> empList = pd.createList();
        
        ConcurrentMap<Character, List<Employee>> bySalary = empList.parallelStream().collect(Collectors.groupingByConcurrent(e -> e.sex));
        bySalary.forEach((K, V)->{
            System.out.println("Key- " + K + " Value ");
            V.forEach(v->System.out.println(v.name));
        });
        
    }
    
    
    // Stub method to create list of employee objects
    private List<Employee> createList(){
        List<Employee> empList = Arrays.asList(new Employee("E001", 40, "Ram", 'M', 5000), 
        new Employee("E002", 35, "Sheila", 'F', 7000), 
        new Employee("E003", 24, "Mukesh", 'M', 9000), 
        new Employee("E004", 37, "Rani", 'F', 10000));
        
        return empList;
    }

    class Employee {
        private String empId;
        private int age;
        private String name;
        private char sex;
        private int salary;
        Employee(String empId, int age, String name, char sex, int salary){
            this.empId = empId;
            this.age = age;
            this.name = name;
            this.sex = sex;
            this.salary = salary;
        }
        
    }
}

Output

Key- F Value 
Sheila
Rani
Key- M Value 
Mukesh
Ram

Using forEachOrdered

The order in which a pipeline processes the elements of a stream depends on whether the stream is executed in serial or in parallel.

As example :

Integer[] intArray = {1, 2, 3, 4, 5, 6, 7, 8 };
List<Integer> listOfIntegers = new ArrayList<>(Arrays.asList(intArray));
System.out.println("listOfIntegers:");
listOfIntegers.stream().forEach(e -> System.out.print(e + " "));

Output

listOfIntegers:
1 2 3 4 5 6 7 8

Here you can see that the pipeline prints the elements of the list listOfIntegers in the order that they were added to the list.

With parallel stream -

System.out.println("Parallel stream");
listOfIntegers.parallelStream().forEach(e -> System.out.print(e + " "));

Output

Parallel stream:
3 4 1 6 2 5 7 8

Here you can see that the pipeline prints the elements of the list in an apparently random order. When you execute a stream in parallel, the Java compiler and runtime determine the order in which to process the stream's elements to maximize the benefits of parallel computing unless otherwise specified by the stream operation.

Using forEachOrdered -

System.out.println("With forEachOrdered:");
listOfIntegers.parallelStream().forEachOrdered(e -> System.out.print(e + " "));

Output

With forEachOrdered:
8 7 6 5 4 3 2 1

Note that the method forEachOrdered is used here, which processes the elements of the stream in the order specified by its source, regardless of whether you executed the stream in serial or parallel. Note that you may lose the benefits of parallelism if you use operations like forEachOrdered with parallel streams.

Points to note

  1. Parallelism is not automatically faster than performing operations serially, although it can be if you have enough data and processor cores.
  2. There is increased overhead of splitting the data, managing multiple threads, combining the partial results.
  3. Make sure that there is enough data for computation that offsets this increased overhead and time saved in parallely processing the data scores over any overhead tasks.
  4. Performance of parallel execution also depends upon the number of processors available.

That's all for this topic Parallel Stream in Java Stream API. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. Stream API in Java 8
  2. Java Stream API Examples
  3. Reduction Operations in Java Stream API
  4. Lambda expressions in Java 8

You may also like -

>>>Go to Java advance topics page