Introduction to Java Stream API

Introduction to Java Stream API

Java Stream API is there since Java 8. It is used to express computation on data is a short and elegant way. In the following post I will introduce you to the most common methods to give you an idea what you can achieve with the Java Stream API.

Java Stream API is there since Java 8. It is used to express computation on data is a short and elegant way. In the following post I will introduce you to the most common methods to give you an idea what you can achieve with the Java Stream API.

Streams vs Collections

Before jumping right into the code I want to explain the difference between Streams and Collections. It is clear that both have properties in common, they can both be iterated for example. You can iterate through Collection external with e.g. for each loops. Instead you don't loop explicit through streams. You express your computations in a functional way and the Stream API deals for iterations internally. Also the Stream API is lazy, its elements are computed or fetched via network by demand. Collections are a in memory data store which means that every element in your Collection has to be computed and stored in your RAM before you can access it. But this does not mean that you can't use streams for already computed data. It rather makes Streams more flexible than Collections in specific situations. You also can create Streams out of Collection based data structures as I will do in the following examples.

Examples

In the following I will show you some examples of the usage of Streams and I will also compare my solution to the classical programming approach.

filter

If you want to filter a list, you can just use filter.

Let's assume we have a list of words.

List<String> words = Arrays.asList("Abra", "Kadrabra", "Aloha");

Now we want to filter all words which starts with a capital A and print them.

words.stream()
        .filter(word -> word.startsWith("A"))
        .forEach(System.out::println);

We actually use two stream methods here. First we transform the list to a stream and filter and words which starts with a capital A. On the resulting stream we are printing out every word with System.out.println.

You probably have seen similar lambda expressions like the on in the filter before, but maye you have not seen many which I used in the forEach method. System.out::println is just syntactic sugar for following lambda expression: x -> System.out.println(x).

We can also write the code by not using streams by simply using a for loop:

for (String word : words) {
        if (word.startsWith("A")) {
            System.out.println(word);
    }
}

This solution is in my opinion less elegant and can be written more expressive as I showed in the upper code snippet.

We can even improve our Stream example by creating a method for the startsWith condition in a external method.

words.stream()
        .filter(StreamExamples::startsWithA)
        .forEach(System.out::println);

with

private static boolean startsWithA(String word) {
    return word.startsWith("A");
}

sum

With the Stream API you also never have to write code like this again

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

int sum = 0;
for (Integer number : numbers) {
    sum += number;
}
System.out.println(sum);

Instead you can write

System.out.println(numbers.stream().mapToInt(Integer::intValue).sum());

which does exactly the same as the upper code snippet.

map

map projects every element of a stream into another form. As I used mapToInt to project the element to Int's, I can use map to project every element of a stream in to a new element.

numbers.stream()
        .map(number -> number * number)
        .forEach(System.out::println);

A traditional approach of writing this code would be following snippet:

for (Integer number : numbers) {
    int squaredNumber = number * number;
    System.out.println(squaredNumber);
}

flatMap

Next lets assume we have following data source:

List<List<Integer>> matrix = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4), Arrays.asList(5, 6));

Our task is it now to sum up all element in the matrix.

To flat the data structure we can use flatMap. It concatenates streams and generates a single stream as a result. So to compute the sum, we can use first flatMap to concatenate multiple streams into one and then use mapToIntand sum as shown in the upper example of sum.

System.out.println(matrix.stream().flatMap(Collection::stream).mapToInt(Integer::intValue).sum());

flatMap allows use to abstain from for-loops in for-loops and write elegant code in one line.

Your colleagues will thank you if they pull your code.

collect

Last but not least you can transform a stream into a traditional data structure by using collect.

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

List<Integer> evenNumbers = numbers.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());

Conclusion

I have uploaded all examples to my Github

Java 8 introduced Java Streams which allows us to express data processing queries in a short functional and elegant way. There are many more operations to explore, this post should just gave you an introduction to the Stream API. I hope you are motivated now to use the Stream API next time when you are using Java.

Java Reflection API Tutorial

Java Reflection API Tutorial

Reflection API in Java is used to manipulate class and its members which include fields, methods, constructor, etc. at runtime. One advantage of reflection API in Java is, it can manipulate private members of the class too

What is Reflection in Java?

Java Reflection is the process of analyzing and modifying all the capabilities of a class at runtime. Reflection API in Java is used to manipulate class and its members which include fields, methods, constructor, etc. at runtime.

One advantage of reflection API in Java is, it can manipulate private members of the class too.

The java.lang.reflect package provides many classes to implement reflection java.Methods of the java.lang.Class class is used to gather the complete metadata of a particular class.

Class in java.lang.reflect Package

Following is a list of various Java classes in java.lang.package to implement reflection-

Field: This class is used to gather declarative information such as datatype, access modifier, name and value of a variable.

Method: This class is used to gather declarative information such as access modifier, return type, name, parameter types and exception type of a method.

Constructor: This class is used to gather declarative information such as access modifier, name and parameter types of a constructor.

Modifier: This class is used to gather information about a particular access modifier.

Methods used in java.lang.Class

Public String getName (): Returns the name of the class.

Public Class getSuperclass(): Returns the super class reference

Public Class[] getInterfaces() : Returns an array of interfaces implemented by the specified class

Public in getModifiers (): Returns an integer value representing the modifiers of the specified class which needs to be passed as a parameter to "public static String toString (int i )" method which returns the access specifier for the given class.

How to get complete information about a class

To get information about variables, methods, and constructors of a class, we need to create an object of the class.

public class Guru99ClassObjectCreation {
	public static void main (String[] args) throws ClassNotFoundException {
		//1 - By using Class.forname() method 
		Class c1 = Class.forName("Guru99ClassObjectCreation"); 
		//2- By using getClass() method 
		Guru99ClassObjectCreation guru99Obj = new Guru99ClassObjectCreation();
		Class c2 = guru99Obj.getClass();
		//3- By using .class 
		Class c3= Guru99ClassObjectCreation.class;
		}
	}

Following example shows different ways to create object of class "class" :

Example 1 : How to get Metadata of Class

Following example shows how to get metadata such as: Class name, super class name, implemented interfaces, and access modifiers of a class.

We will get the metadata of below class named Guru99Base.class:

import java.io.Serializable;
public abstract class Guru99Base implements Serializable,Cloneable {
}
  1. Name of the class is: Guru99Base
  2. It's access modifiers are: public and abstract
  3. It has implemented interfaces: Serializable and Cloneable
  4. Since it has not extended any class explicitly, it's super class is: java.lang.Object

Below class will get the meta data of Guru99Base.class and print it:

import java.lang.reflect.Modifier;
public class Guru99GetclassMetaData {
public static void main (String [] args) throws ClassNotFoundException { 
// Create Class object for Guru99Base.class 
Class guru99ClassObj = Guru99Base.class;

// Print name of the class 
system.out.println("Name of the class is : " +guru99ClassObj.getName());

// Print Super class name
system.out.println("Name of the super class is : " +guru99ClassObj.getSuperclass().getName());

// Get the list of implemented interfaces in the form of Class array using getInterface() method
class[] guru99InterfaceList = guru99classObj.getInterfaces();

// Print the implemented interfaces using foreach loop 
system.out.print("Implemented interfaces are : ");
for (Class guru99class1 : quru99 InterfaceList)	{
	system.out.print guru99class1.getName() + " ");
}
system.out.println();

//Get access modifiers using get Modifiers() method and toString() method of java.lang.reflect.Modifier class
int guru99AccessModifier= guru99classObj.getModifiers(); 
// Print the access modifiers
System.Out.println("Access modifiers of the class are : " +Modifier.tostring(guru99AccessModifier));

}

}

  1. print the name of the class using getName method
  2. Print the name of the super class using getSuperClass().getName() method
  3. Print the name of the implemented interfaces
  4. Print the access modifiers used by the class

Example 2 : How to get Metadata of Variable

Following examples shows how to get metadata of variable:

Here, we are creating a class named Guru99VariableMetaData .class with some variables:

package guru;
public class Guru99VariableMetaData {
public static int guru99IntVar1=1111;
static int guru99IntVar2=2222;
static String guru99StringVar1="guru99.com";
static String guru99StringVar2="Learning Reflection API";
}

Steps to get the metadata about the variables in the above class:

Create the class object of the above class i.e. Guru99VariableMetaData.class as below:

  Guru99VariableMetaData  guru99ClassVar  = new Guru99VariableMetaData();
Class guru99ClassObjVar = guru99ClassVar.getClass();

Get the metadata in the form of field array using getFields() or getDeclaredFields() methods as below:

Field[]  guru99Field1= guru99ClassObjVar .getFields();
Field[] guru99Fiel2= guru99ClassObjVar .getDeclaredFields();

getFields() method returns metadata of the public variable from the specified class as well as from its super class.

getDeclaredFields() method returns metadata of the all the variables from the specified class only.

  1. Get the name of the variables using "public String getName()" method.
  2. Get the datatype of the variables using "public Class getType()" method.
  3. Get the value of the variable using "public xxx get (Field)" method.
  4. Here, xxx could be a byte or short of any type of value we want to fetch.
  5. Get the access modifiers of the variables using getModifier() and Modifier.toString(int i) methods.
  6. Here, we are writing a class to get the metadata of the variables present in the class Guru99VariableMetaData .class:
package guru;
import java.lang.reflect.Field;

public class Guru99VariableMetaDataTest {
public static void main(String[] args) throws IllegalArgumentException, IllegalAccessException {
// Create Class object for Guru99VariableMetaData.class
Guru99VariableMetaData guru99ClassVar = new Guru99VariableMetaData();
Class guru99ClassObjVar = guru99ClassVar.getClass();

// Get the metadata of all the fields of the class Guru99VariableMetaData 
Field[] guru99Field1= guru99ClassObjVar.getDeclaredFields();

// Print name, datatypes, access modifiers and values of the varibales of the specified class 
for(Field field : guru99Field1) { 
System.out.println("Variable name : "+field.getName());
System.out.println("Datatypes of the variable :"+field.getType());

int guru99AccessModifiers = field.getModifiers();
System.out.printlln("Access Modifiers of the variable : "+Modifier.toString(guru99AccessModifiers));
System.out.println("Value of the variable : "+field.get(field));
System.out.println();
system.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *") ;
}
}

}

  1. Created class object for Guru99VariableMetaData.class
  2. Got all the metadata of the variables in a Field array
  3. Printed all the variable names in the class Guru99VariableMetaData.class
  4. Printed all the data types of the variables in the class Guru99VariableMetaData.class
  5. Printed all the access modifiers of the variables in the class Guru99VariableMetaData.class
  6. Printed values of all the variables in Printed all the data types of the variables in the class Guru99VariableMetaData.class
Example 3 : How to get Metadata of Method
  1. Following examples shows how to get metadata of a method:
  2. Here, we are creating a class named Guru99MethodMetaData .class with some methods
package guru;		
import java.sql.SQLException;
public class Guru99MethodMetaData {

public void guru99Add(int firstElement, int secondElement , String result) 									
throws ClassNotFoundException, ClassCastException{			
      System.out.println("Demo method for Reflextion  API");					
}	
public String guru99Search(String searchString) 			
throws ArithmeticException, InterruptedException{			
    System.out.println("Demo method for Reflection API");					
	return null;					
}	
public void guru99Delete(String deleteString) 					
throws SQLException{			
    System.out.println("Demo method for Reflection API");					
}	

}

Steps to get the metadata about the methods in the above class :

Create the class object of the above class i.e. Guru99MethodMetaData.class as below:

Guru99MethodMetaData  guru99ClassVar  = new Guru99MethodMetaData  ();
Class guru99ClassObjVar = guru99ClassVar.getClass();

Get method information in a Method array using getMethods() and getDeclaredMethods() method as below:

Method[]  guru99 Method 1= guru99ClassObjVar .get Methods();
Method [] guru99 Method 2= guru99ClassObjVar .getDeclared Method s();

getMethods() method returns metadata of the public methods from the specified class as well as from its super class.

getDeclaredMethods() method returns metadata of the all the methods from the specified class only.

Get the name of the method using getName() method.

Get the return type of the method using getReturnType() method.

Get access modifiers of the methods using getModifiers() and Modifiers.toString(int i) methods.

Get method parameter types using getParameterTypes() method which returns a class array.

Get thrown exception using getExceptionTypes() method which returns a class array.

Here, we are writing a class to get the metadata of the methods present in the class Guru99MethodMetaData.class:

package guru;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class Guru99MethodMetaDataTest {

public static void main (String[] args) {
	// Create Class object for Guru99Method MetaData.class 
	class guru99ClassObj = Guru99MethodMetaData.class;

	// Get the metadata or information of all the methods of the class using getDeclaredMethods() 
	Method[] guru99Methods=guru99classObj.getDeclaredMethods();

	for(Method method : guru99Methods) { 
	// Print the method names
	System.out.println("Name of the method : "+method.getName());
	
	// Print return type of the methods 
	System.out.println("Return type of the method : "+method.getReturnType());
	
	//Get the access modifier list and print
	int guru99ModifierList = method.getModifiers(); 
	System.Out.printlin ("Method access modifiers : "+Modifier.toString(guru99ModifierList));
	
	// Get and print parameters of the methods 
	Class[] guru99ParamList= method.getParameterTypes(); 
	system.out.print ("Method parameter types : "); 
	for (Class class1 : guru99ParamList){ 
		System.out.println(class1.getName()+" ");
	}
    System.out.println();
	
	// Get and print exception thrown by the method 
	Class[] guru99ExceptionList = method. getExceptionTypes(); 
	system.out.print("Excpetion thrown by method :"); 
	for (Class class1 : guru99ExceptionList) {
		System.out.println (class1.getName() +" "):
	} 
	System.Out.println(); 
	system.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * ");
	
	}

}

}

Created class object for Guru99MethodMetaData.class

Got all the metadata of all the methods in a Method array

Printed all the method names present in the class Guru99MethodMetaData.class

Printed return types of the methods in the class Guru99MethodMetaData.class

Printed all the access modifiers of the methods in the class Guru99MethodMetaData.class

Printed parameter types of the methods in Guru99MethodMetaData.class

Printed exceptions are thrown by methods in Guru99MethodMetaData.class

Example 4 : How to get Metadata of Constructors
  1. Following examples shows how to get metadata of constructors:
  2. Here, we are creating a class named Guru99Constructor.class with different constructors:
package guru;

import java.rmi.RemoteException;
import java.sql.SQLException;

public class Guru99Constructor {

public Guru99Constructor(int no) throws ClassCastException ,ArithmeticException{  }							
public Guru99Constructor(int no, String name) throws RemoteException ,SQLException{  }							
public Guru99Constructor(int no, String name, String address) throws InterruptedException{  }							

}

Here, we are writing a class to get the metadata of the constructors present in the class Guru99Constructor.class:

package guru;
import java.lang.reflect.Constructor;
public class Guru99ConstructorMetaDataTest {

public static void main (String[] args) {
	// Create Class object for Guru99Constructor.class 
	Class guru99Class=Guru99Constructor.class;

	// Get all the constructor information in the Constructor array
	Constructor[] guru99ConstructorList = guru99Class.getConstructors();
	
	for (Constructor constructor : guru99ConstructorList) {
		// Print all name of each constructor
		System.out.println("Constrcutor name : "+constructor.getName());
		
		//Get and print access modifiers of each constructor 
		int guru99Modifiers= constructor.getModifiers(); 
		System.Out.printlin ("Constrctor modifier : "+Modifier.toString(guru99Modifiers));
		
		// Get and print parameter types 
		Class[] guru99ParamList=constructor.getParameterTypes();
		System.out.print ("Constrctor parameter types :"); 
		for (Class class1 : guru99ParamList) { 
			System.out.println(class1.getName() +" ");
		}
		System. out.println();

		// Get and print exception thrown by constructors
		Class[] guru99ExceptionList=constructor.getFxceptionTypes();
		System.out.println("Exception thrown by constructors :"); 
		for (Class class1 : guru99ExceptionList) { 
			System.out.println(class1.getName() +" ");
		} 
		System.out.println();
		System.out.println("*******************************************");
	}
}

}

  1. Created class object for Guru99Constructor.class
  2. Got all the metadata of all the constructors in a Constructor array
  3. Printed all the constructor's names present in the class Guru99Constructor.class
  4. Printed all the access modifiers of the constructors in the class Guru99Constructor.class
  5. Printed parameter types of the constructors in Guru99Constructor.class
  6. Printed exceptions are thrown by constructors in Guru99Constructor.class
Summary:
  • Reflection programming in java helps in retrieving and modifying information about Classes and Class members such variable, methods, constructors.
  • Reflection API in Java can be implemented using classes in java.lang.reflect package and methods of java.lang.Class class.
  • Some commonly used methods of java.lang.Class class are getName (), getSuperclass (), getInterfaces (), getModifiers () etc.
  • Some commonly used classes in java.lang.reflect package are Field, Method, Constructor, Modifier, etc.
  • Reflection API can access private methods and variables of a class which could be a security threat.
  • Reflection API is a powerful capability provided by Java, but it comes with some overheads such as slower performance, security vulnerability, and permission issue. Hence, reflection API should be treated as the last resort to performing an operation.


Thanks for reading. If you liked this post, share it with all of your programming buddies!

Originally published on guru99.com

Test a REST API with Java

Test a REST API with Java

This tutorial focuses on the basic principles and mechanics of testing a REST API with live Integration Tests (with a JSON payload).

This tutorial focuses on the basic principles and mechanics of testing a REST API with live Integration Tests (with a JSON payload).

1. Overview

The main goal is to provide an introduction to testing the basic correctness of the API – and we’re going to be using the latest version of the GitHub REST API for the examples.

For an internal application, this kind of testing will usually run as a late step in a Continuous Integration process, consuming the REST API after it has already been deployed.

When testing a REST resource, there are usually a few orthogonal responsibilities the tests should focus on:

  • the HTTP response code
  • other HTTP headers in the response
  • the payload (JSON, XML)

Each test should only focus on a single responsibility and include a single assertion. Focusing on a clear separation always has benefits, but when doing this kind of black box testing is even more important, as the general tendency is to write complex test scenarios in the very beginning.

Another important aspect of the integration tests is adherence to the Single Level of Abstraction Principle – the logic within a test should be written at a high level. Details such as creating the request, sending the HTTP request to the server, dealing with IO, etc should not be done inline but via utility methods.

2. Testing the Status Code
@Test
public void givenUserDoesNotExists_whenUserInfoIsRetrieved_then404IsReceived()
  throws ClientProtocolException, IOException {
  
    // Given
    String name = RandomStringUtils.randomAlphabetic( 8 );
    HttpUriRequest request = new HttpGet( "https://api.github.com/users/" + name );
 
    // When
    HttpResponse httpResponse = HttpClientBuilder.create().build().execute( request );
 
    // Then
    assertThat(
      httpResponse.getStatusLine().getStatusCode(),
      equalTo(HttpStatus.SC_NOT_FOUND));
}

This is a rather simple test – it verifies that a basic happy path is working, without adding too much complexity to the test suite.

If for whatever reason, it fails, then there is no need to look at any other test for this URL until this is fixed.

3. Testing the Media Type
@Test
public void
givenRequestWithNoAcceptHeader_whenRequestIsExecuted_thenDefaultResponseContentTypeIsJson()
  throws ClientProtocolException, IOException {
  
   // Given
   String jsonMimeType = "application/json";
   HttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );
 
   // When
   HttpResponse response = HttpClientBuilder.create().build().execute( request );
 
   // Then
   String mimeType = ContentType.getOrDefault(response.getEntity()).getMimeType();
   assertEquals( jsonMimeType, mimeType );
}

This ensures that the Response actually contains JSON data.

As you might have noticed, we’re following a logical progression of tests – first the Response Status Code (to ensure that the request was OK), then the Media Type of the Response, and only in the next test will we look at the actual JSON payload.

4. Testing the JSON Payload
@Test
public void
  givenUserExists_whenUserInformationIsRetrieved_thenRetrievedResourceIsCorrect()
  throws ClientProtocolException, IOException {
  
    // Given
    HttpUriRequest request = new HttpGet( "https://api.github.com/users/eugenp" );
 
    // When
    HttpResponse response = HttpClientBuilder.create().build().execute( request );
 
    // Then
    GitHubUser resource = RetrieveUtil.retrieveResourceFromResponse(
      response, GitHubUser.class);
    assertThat( "eugenp", Matchers.is( resource.getLogin() ) );
}

In this case, I know the default representation of GitHub resources is JSON, but usually, the Content-Type header of the response should be tested alongside the Accept header of the request – the client asks for a particular type of representation via Accept, which the server should honor.

5. Utilities for Testing

We’re going to use Jackson 2 to unmarshall the raw JSON String into a type-safe Java Entity:

public class GitHubUser {
 
    private String login;
 
    // standard getters and setters
}

We’re only using a simple utility to keep the tests clean, readable and at a high level of abstraction:

public static <T> T retrieveResourceFromResponse(HttpResponse response, Class<T> clazz)
  throws IOException {
  
    String jsonFromResponse = EntityUtils.toString(response.getEntity());
    ObjectMapper mapper = new ObjectMapper()
      .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    return mapper.readValue(jsonFromResponse, clazz);
}

Notice that Jackson is ignoring unknown properties that the GitHub API is sending our way – that’s simply because the Representation of a User Resource on GitHub gets pretty complex – and we don’t need any of that information here.

6. Dependencies

The utilities and tests make use of the following libraries, all available in Maven central:

7. Conclusion

This is only one part of what the complete integration testing suite should be. The tests focus on ensuring basic correctness for the REST API, without going into more complex scenarios,

For example, the following are not covered: Discoverability of the API, consumption of different representations for the same Resource, etc.

The implementation of all these examples and code snippets can be found over on Github – this is a Maven-based project, so it should be easy to import and run as it is.

Java Stream API Was Broken Before JDK 10

Java Stream API Was Broken Before JDK 10

In this post, we learn more about a few deficiencies surrounding Java Stream API Was Broken Before JDK 10

In this post, we learn more about a few deficiencies surrounding Java Stream API Was Broken Before JDK 10

Stream API bugs can affect anyone still residing on JDK 8 and JDK 9.

Of course, not all of it, but history showed that Stream API featured a few interesting bugs/deficiencies that can affect anyone still residing on JDK 8 and JDK 9.

Stream#flatMap

Unfortunately, it turns out that Stream#flatMap was not as lazy as advertised, which allowed for several crazy situations to exist.

For example, let’s take this one:

Stream.of(1)
  .flatMap(i -> Stream.generate(() -> 42))
  .findAny()
  .ifPresent(System.out::println);

In JDK 8 and JDK 9, the above code snippet spins forever waiting for the evaluation of the inner infinite Stream.

One would expect O(1) time complexity from a trivial operation of taking a single element from an infinite sequence — and this is how it works as long as we don’t process an infinite Stream inside Stream#flatMap:

Stream.generate(() -> 42)
  .findAny()
  .ifPresent(System.out::println);

// completes "immediately" and prints 42

What’s more, it gets worse if we insert some additional processing after a short-circuited Stream#flatMap call:

Stream.of(1)
  .flatMap(i -> Stream.generate(() -> 42))
  .map(i -> process(i))
  .findAny()
  .ifPresent(System.out::println);
private static <T> T process(T input) {
    System.out.println("Processing...");
    return input;
}

Now, not only are we stuck in an infinite evaluation loop, but we’re also processing all of items coming through:

Processing...
Processing...
Processing...
Processing...
Processing...
Processing...
Processing...
Processing...
Processing...
Processing...
Processing...
Processing...
...

Imagine the consequences if the process() method contained some blocking operations and unwanted side-effects like email send outs or logging.

Explanation

The internal implementation of [Stream#flatMap](https://bugs.openjdk.java.net/browse/JDK-8075939 "Stream#flatMap") is to blame, especially the following code:

@Override
public void accept(P_OUT u) {
    try (Stream<? extends R> result = mapper.apply(u)) {
        // We can do better that this too; optimize for depth=0 case and just grab spliterator and forEach it
        if (result != null)
            result.sequential().forEach(downstream);
    }
}

As you can see, the inner Stream is consumed eagerly using Stream#forEach (not even mentioning the lack of curly braces around the conditional statement. Ugh!).

The problem remained unaddressed in JDK 9, but luckily, the solution was shipped with JDK 10:

@Override
public void accept(P_OUT u) {
    try (Stream<? extends R> result = mapper.apply(u)) {
        if (result != null) {
            if (!cancellationRequestedCalled) {
                result.sequential().forEach(downstream);
            }
            else {
                var s = result.sequential().spliterator();
                do { } while (!downstream.cancellationRequested() && s.tryAdvance(downstream));
            }
        }
    }
}

Stream#takeWhile/dropWhile

This one is directly connected to the above one and Stream#flatMap’s unwanted eager evaluation.

Let’s say we have a list of lists:

List<List<String>> list = List.of(
  List.of("1", "2"),
  List.of("3", "4", "5", "6", "7"));

And, we want to flatten them into a single one:

list.stream()
  .flatMap(Collection::stream)
  .forEach(System.out::println);

// 1
// 2
// 3
// 4
// 5
// 6
// 7

It works just as expected.

Now, let’s take the flattened the Stream and simply keep taking elements until we encounter “4:"

Stream.of("1", "2", "3", "4", "5", "6", "7")
  .takeWhile(i -> !i.equals("4"))
  .forEach(System.out::println);

// 1
// 2
// 3

Again, it works just as we expected.

Let’s now try to combine these two; what could go wrong?

List<List<String>> list = List.of(
  List.of("1", "2"),
  List.of("3", "4", "5", "6", "7"));

list.stream()
  .flatMap(Collection::stream)
  .takeWhile(i -> !i.equals("4"))
  .forEach(System.out::println);

// 1
// 2
// 3
// 5
// 6
// 7

That’s an unexpected turn of events and can be fully attributed to the original issue with Stream#flatMap.

Some time ago, I did run a short poll on Twitter, most of you were quite surprised with the result:

Parallel Streams on Custom ForkJoinPool Instances

There’s one commonly-known hack (that you should not be using since it relies on internal implementation details of Stream API) that makes it possible to hijack parallel Stream tasks and run them on the custom fork-join pool by running them from within your own FJP instance:

ForkJoinPool customPool = new ForkJoinPool(42);

customPool.submit(() -> list.parallelStream() /*...*/);

If you thought that you managed to trick everyone already, you were partially right.

It turns out that even though tasks were running on a custom pool instance, they were still coupled to the shared pool – the size of the computation would remain in proportion to the common pool and not the custom pool – JDK-8190974.

So, even if you were using these when you shouldn’t have, the fix for that arrived in JDK 10. Additionally, if you really need to use Stream API to run parallel computations, you could use parallel-collectorsinstead.