Core Java

Java 8 Array to Stream Example

1. Introduction

Official javadoc of java.util.stream.Stream states that it is “A sequence of elements supporting sequential and parallel aggregate operations”. And such every Stream is backed by a source which would provide the Stream with its “sequence of elements”. In Java, like most other programming languages, sequence of elements is generally provided via two constructs: (i) the java.util.Collection instances and (ii) the classical array.
 
 
 
 

 
In this post we are concerned with arrays and see how Streams can further make array processing easier and efficient. In fact the Stream documentation explicitly mention that arrays are valid source candidates for supplying Stream its sequence of elements: “A stream pipeline consists of a source (which might be an array, a collection, a generator function, an I/O channel, etc)”. We would see all the standard filter-map-reduce operations work exactly the same way as with Collection instances!

2. Creating Streams out of Arrays

The simplest, effective way of easily creating Stream out of an array is to use one of the several overloaded static factory methods from java.util.Arrays class. There are basically two flavors of factory methods: firstly, there are those methods which return Stream backed by primitive data types like int, float etc, and then there are those which return Stream backed by reference (of object) types. In the following sections we would see both these flavors in practice

2.1 Streams from primitive data arrays

Lets say we have an integer array of age of students in a class:

Instantiating an array of ints

int[] classAge = new int[]{21,25,27,24,26};

Then to seek an Stream from the above array, all we need to say is,

Creating Stream out of array of ints

IntStream ageStream = Arrays.stream(classAge); 

Notice the return type of the factory method, it is java.util.stream.IntStream and not java.util.stream.Stream! Well, IntStream is a specialized form of Stream interface which deals specifically with sequence of primitive int type elements and as such it reduces the overhead of boxing-unboxing to and from java.lang.Integer objects.

Once we have IntStream in hand, all standard Stream operations can be applied as is. Consider some of the many operations that could be applied.

Filter operation, we want only even numbered ages:

Filter Operation

IntStream evenAges = ageStream.filter(age -> age %2 == 0);

Map Operation, we double the age of each student:

Map Operation

IntStream doubleAges = evenAges.map(age -> age*2);

Finally, we do an aggregating/reducing operation on the overall Stream:

Aggregating Operation

int sum = doubleAges.sum();

Here is the complete example source code:

Streams from primitive data arrays

package arraytostream;

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

public class Java8ArrayToStreamExample {

	public static void main(String[] args) {
		int[] classAge = new int[]{21,25,27,24,26};
		IntStream ageStream = Arrays.stream(classAge);
		
		//filter operation
		IntStream evenAges = ageStream.filter(age -> age %2 == 0);
		
		//map operation
		IntStream doubleAges = evenAges.map(age -> age*2);
		
		//aggregate operation
		int sum = doubleAges.sum();
		
		System.out.println(sum);
	}

}

2.2 Stream from array of object references

We just saw how Stream backed by primitive Java data types can be created and processed. Similarly, Streams can be culled out of arrays of object instances as well. We will slightly modify the semantics of the above example; now we would encapsulate the age of each student in an Student object and do similar operations as we did before!

Following is our Student class:

Student.java

package arraytostream;

public class Student {
	
	String name;
	int age;
	
	public Student (String name, int age){
		this.name = name;
		this.age = age;
	}
	
	public String getName() {
		return name;
	}
	public int getAge() {
		return age;
	}
}

Like before we will initialize an array of students:

Instantiating array of Student instances

Student [] studArray = new Student[] {new Student("Mohammad", 30),
                                      new Student("Nawazish", 31),
				      new Student("khan", 32)
				     };

After this, we can again use factory method from Arrays class to have a Stream of Student!

Creating Stream backed by array of Student instances

//Streams backed by array of Students
Stream studStream = Arrays.stream(studArray);

Notice unlike before, this time we are having an array of objects (not primitives), and hence we do not have the primitive xxxStreamreturned by the static factory method, rather this returns the generic Stream type.

Once we have the Stream of Student, we can have all standard Stream operation done; for instance we will do filter operation in the following code:

Filter Operation

//Filter operation; only those students with even numbered age
Stream evenAgedStudent = studStream.filter(student-> student.getAge()%2 == 0);

Similarly we may also perform mapping operations:

Map Operation

//Map each student's age by half
Stream halfAge = evenAgedStudent.map(student -> {
			return new Student(student.getName(), student.getAge()*2);
		});

Following is the complete source code:

Stream from array of object references

package arraytostream;

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

public class Java8ArrayRefToStreamExample {

	public static void main(String[] args) {
		Student [] studArray = new Student[] {new Student("Mohammad", 30),
						      new Student("Nawazish", 31),
						      new Student("khan", 32)
						     };
		//Streams backed by array of Students
		Stream studStream = Arrays.stream(studArray);
		
		//Filter operation; only those students with even numbered age
		Stream evenAgedStudent = studStream.filter(student-> student.getAge()%2 == 0);
		
		//Map each student's age by half
		Stream halfAge = evenAgedStudent.map(student -> {
			return new Student(student.getName(), student.getAge()*2);
		});
		
		halfAge.forEach(student-> System.out.println(student.getName()+" :"+student.getAge()));		
	}
}

3. Conclusion

This example was about backing Streams from an underlying array as source. We saw how easy this is especially when we have library class like Arrays with its static factory method. Once a Stream instance is created from an underlying array source, further Stream operations remains the same.

Nawazish Khan

I am Nawazish, graduated in Electrical Engineering, in 2007. I work as a Senior Software Engineer with GlobalLogic India Ltd (Banglore) in the Telecom/Surveillance domain. A Java Community Process (JCP) member with an unconditional love (platform, technology, language, environment etc does not matter) for computer programming. Extremely interested programming multi-threaded applications, IoT devices (on top of JavaME) and application containers. The latest language of interest being Google Go; and Neo4j as the NoSQL Graph Database solution.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
DP20
DP20
5 years ago

I am getting error for Stream functions on Non-primitive array types. For stream functions, object has to convert to Student, as below :-

Student[] studArray = new Student[] { new Student(“Mohammad”, 30), new Student(“Nawazish”, 31),
new Student(“khan”, 32) };

Stream studStream = Arrays.stream(studArray);
Stream evenAgedStudent = studStream.filter(student -> ((Student) student).getAge() % 2 == 0);

Please suggest.

Back to top button