Java 8 Join Arrays Example
1. Introduction
An Array is a data structure which holds a fixed number of objects with the same type. Joining Arrays is to combine two arrays into one. Java 8 enhances Collection by providing a new Stream interface. A stream is not a data structure, instead it is created from Collection, Array, or I/O channels.
Java 8 provides a Stream interface which contains several methods that we can use to join two arrays.
Return type | Method | Description |
---|---|---|
static <T> Stream<T> | concat(Stream<? extends T> a, Stream<? extends T> b) | Creates a lazily concatenated stream whose elements are all the elements of the first stream followed by all the elements of the second stream. |
Object[] | toArray() | Returns an array containing the elements of this stream. |
static <T> Stream<T> | of(T... values) | Returns a sequentially ordered stream whose elements are the specified values. |
<R> Stream<R> | flatMap(Function<? super T,? extends Stream<? extends R>> mapper) | Returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element. |
Java 8 provides the same methods for primitive types: int
, long
, double
as IntStream, LongStream, and DoubleStream respectively.
Interface | Return type | Methods |
---|---|---|
IntStream | static IntStream | concat(IntStream a, IntStream b) |
LongStream | static LongStream | concat(LongStreama, LongStreamb) |
DoubleStream | static DoubleStream | concat(DoubleStreama, DoubleStreamb) |
Java 8 enhances the Arrays class to add the stream
method to create a stream from an Array.
Return type | Method | Description |
---|---|---|
static IntStream | stream(int[] array) | Returns a sequential IntStream with the specified array as its source. |
static DoubleStream | stream(double[] array) | Returns a sequential DoubleStream with the specified array as its source. |
static LongStream | stream(long[] array) | Returns a sequential LongStream with the specified array as its source. |
<T> Stream<T> | stream(T[] array) | Returns a sequential Stream with the specified array as its source. |
In this example, I will demonstrate how to join two arrays in three steps:
- Converting two arrays into two streams: with
Stream.of
orArrays.stream
. - Joining two streams: with
concat
orflatMap
. - Using
toArray
on the joined stream to return it as an array.
2. Technologies Used
The example code in this article was built and run using:
- Java 1.8.101
- Maven 3.3.9
- Eclipse Oxygen
- Junit 4.12
3. Maven Project
3.1 Dependencies
I will include Junit
in pom.xml
.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>zheng.jcg.demo</groupId> <artifactId>java8-join-array</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project>
3.2 SimpleData
I will create a SimpleData
class which will be used to create an array with a user defined data type.
SimpleData.java
package com.zheng.demo; public class SimpleData { public SimpleData(String name, Integer age) { super(); this.name = name; this.age = age; } private String name; private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "SimpleData [name=" + name + ", age=" + age + "]"; } }
3.3 Stream.concat
I will create a JoinArrays_concat
class to join two arrays with the primitive data types – int
, double
, long
and the user defined data type – SimpleData
by using Stream’s concat
method.
JoinArrays_concat.java
package com.zheng.demo; import java.util.Arrays; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; import java.util.stream.Stream; public class JoinArrays_concat { public int[] by_IntStream_concat(int[] int1, int[] int2) { IntStream joinedStream = IntStream.concat(Arrays.stream(int1), Arrays.stream(int2)); return joinedStream.toArray(); } public double[] by_DoubleStream_concat(double[] double1, double[] double2) { DoubleStream joinedStream = DoubleStream.concat(Arrays.stream(double1), Arrays.stream(double2)); return joinedStream.toArray(); } public long[] by_LongStream_concat(long[] long1, long[] long2) { LongStream joinedStream = LongStream.concat(Arrays.stream(long1), Arrays.stream(long2)); return joinedStream.toArray(); } public String[] by_Stream_concat(String[] array1, String[] array2) { Stream stream1 = Arrays.stream(array1); Stream stream2 = Arrays.stream(array2); Stream joinedStream = Stream.concat(stream1, stream2); return joinedStream.toArray(String[]::new); } public String[] by_Stream_concat_2(String[] array1, String[] array2) { Stream stream1 = Stream.of(array1); Stream stream2 = Stream.of(array2); Stream joinedStream = Stream.concat(stream1, stream2); return joinedStream.toArray(String[]::new); } public SimpleData[] by_Stream_concat_Object(SimpleData[] data1, SimpleData[] data2) { Stream joined = Stream.concat(Arrays.stream(data1), Arrays.stream(data2)); return joined.toArray(SimpleData[]::new); } public SimpleData[] by_Stream_concat_Object_2(SimpleData[] data1, SimpleData[] data2) { Stream joinedStream = Stream.concat(Stream.of(data1), Stream.of(data2)); return joinedStream.toArray(SimpleData[]::new); } }
3.4 Stream.flatMap
I will create a JoinArrays_flatmap
class to join two arrays with Stream.flatMap
for String
. and a user defined data type.
JoinArrays_flatmap.java
package com.zheng.demo; import java.util.stream.Stream; public class JoinArrays_flatmap { public String[] by_Stream_of_flatMap(String[] array1, String[] array2) { Stream joinedStream = Stream.of(array1, array2).flatMap(Stream::of); return joinedStream.toArray(String[]::new); } public SimpleData[] by_Stream_of_flatMap_2(SimpleData[] data1, SimpleData[] data2) { Stream joined = Stream.of(data1,data2).flatMap(Stream::of); return joined.toArray(SimpleData[]::new); } }
3.5 System.arraycopy
Java System
class provides arraycopy
to copy an array from the specified source array, beginning at the specified position, to the specified position of the destination array. I will create a JoinArrays_arraycopy
class to join two arrays.
JoinArrays_arraycopy.java
package com.zheng.demo; public class JoinArrays_arraycopy { public <T> T[] concat(T[] a, T[] b) { final int alen = a.length; final int blen = b.length; if (alen == 0) { return b; } if (blen == 0) { return a; } final T[] result = (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), alen + blen); System.arraycopy(a, 0, result, 0, alen); System.arraycopy(b, 0, result, alen, blen); return result; } }
4. Demo
We will demo this with the Junit test classes.
4.1 JoinArrays_concatTest
I will create test cases to join two arrays with different data types: int
, long
, double
, String
, and SimpleData
.
JoinArrays_concatTest.java
package com.zheng.demo; import static org.junit.Assert.assertEquals; import java.util.Arrays; import org.junit.Test; public class JoinArrays_concatTest { private JoinArrays_concat jArray = new JoinArrays_concat(); @Test public void join_arrays_by_IntStream_concat() { int[] int1 = new int[] { 1, 2, 3 }; int[] int2 = new int[] { 4, 5, 6 }; int[] joinedIntArray = jArray.by_IntStream_concat(int1, int2); assertEquals(6, joinedIntArray.length); assertEquals( "[1, 2, 3, 4, 5, 6]" , Arrays.toString(joinedIntArray)); } @Test public void join_arrays_by_DoubleStream_concat() { double[] int1 = new double[] { 1, 2, 3 }; double[] int2 = new double[] { 4, 5, 6 }; double[] joinedArray = jArray.by_DoubleStream_concat(int1, int2); assertEquals(6, joinedArray.length); assertEquals( "[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]" , Arrays.toString(joinedArray)); } @Test public void join_arrays_by_LongStream_concat() { long[] int1 = new long[] { 1, 2, 3 }; long[] int2 = new long[] { 4, 5, 6 }; long[] joinedArray = jArray.by_LongStream_concat(int1, int2); assertEquals(6, joinedArray.length); assertEquals( "[1, 2, 3, 4, 5, 6]" , Arrays.toString(joinedArray)); } @Test public void join_arrays_by_Stream_concat() { String[] animals1 = new String[] { "Dog", "Cat", "Bird" }; String[] animals2 = new String[] { "Bird", "Cow" }; String[] joinedArray = jArray.by_Stream_concat(animals1, animals2); assertEquals(5, joinedArray.length); assertEquals( "[Dog, Cat, Bird, Bird, Cow]" , Arrays.toString(joinedArray)); } @Test public void join_arrays_by_Stream_concat_2() { String[] animals1 = new String[] { "Dog", "Cat", "Bird" }; String[] animals2 = new String[] { "Bird", "Cow" }; String[] joinedArray = jArray.by_Stream_concat_2(animals1, animals2); assertEquals(5, joinedArray.length); assertEquals( "[Dog, Cat, Bird, Bird, Cow]" , Arrays.toString(joinedArray)); } @Test public void join_arrays_by_Stream_concat_Object() { SimpleData[] data1 = {new SimpleData("Mary", 30), new SimpleData("Tom", 40)}; SimpleData[] data2 = {new SimpleData("Bob", 18), new SimpleData("John", 60)}; SimpleData[] joinedArray = jArray.by_Stream_concat_Object(data1, data2); assertEquals(4, joinedArray.length); Arrays.stream(joinedArray).forEach(e->System.out.println(e.toString())); } @Test public void join_arrays_by_Stream_concat_Object_2() { SimpleData[] data1 = {new SimpleData("Mary", 30), new SimpleData("Tom", 40)}; SimpleData[] data2 = {new SimpleData("Bob", 18), new SimpleData("John", 60)}; SimpleData[] joinedArray = jArray.by_Stream_concat_Object_2(data1, data2); assertEquals(4, joinedArray.length); Arrays.stream(joinedArray).forEach(e->System.out.println(e.toString())); } }
4.2 JoinArrays_flatmapTest
I will create test cases to join two arrays for two data types: String
and SimpleData
.
JoinArrays_flatmapTest.java
package com.zheng.demo; import static org.junit.Assert.assertEquals; import java.util.Arrays; import org.junit.Test; public class JoinArrays_flatmapTest { private JoinArrays_flatmap jArray = new JoinArrays_flatmap(); @Test public void join_arrays_by_Stream_of_flatMap() { String[] animals1 = new String[] { "Dog", "Cat", "Bird" }; String[] animals2 = new String[] { "Bird", "Cow" }; String[] joinedArray = jArray.by_Stream_of_flatMap(animals1, animals2); assertEquals(5, joinedArray.length); assertEquals("[Dog, Cat, Bird, Bird, Cow]", Arrays.toString(joinedArray)); } @Test public void join_arrays_by_Stream_of_flatMap_2() { SimpleData[] data1 = {new SimpleData("Mary", 30), new SimpleData("Tom", 40)}; SimpleData[] data2 = {new SimpleData("Bob", 18), new SimpleData("John", 60)}; SimpleData[] joinedArray = jArray.by_Stream_of_flatMap_2(data1, data2); assertEquals(4, joinedArray.length); Arrays.stream(joinedArray).forEach(e->System.out.println(e.toString())); } }
4.1 JoinArrays_arraycopyTest
I will create test cases to join two arrays for data types: Integer
, Long
, String
, and SimpleData
.
JoinArrays_arraycopyTest.java
package com.zheng.demo; import static org.junit.Assert.*; import java.util.Arrays; import org.junit.Test; public class JoinArrays_arraycopyTest { private JoinArrays_arraycopy testObject = new JoinArrays_arraycopy(); @Test public void join_two_Integer_arrays() { Integer[] int1 = new Integer[] { 1, 2, 3 }; Integer[] int2 = new Integer[] { 4, 5, 6 }; Integer[] joinedArray = testObject.concat(int1, int2); assertEquals(6, joinedArray.length); assertEquals( "[1, 2, 3, 4, 5, 6]" , Arrays.toString(joinedArray)); } @Test public void join_two_Long_arrays() { Long[] int1 = new Long[] { 1l, 2l, 3l }; Long[] int2 = new Long[] { 4l, 5l, 6l }; Long[] joinedArray = testObject.concat(int1, int2); assertEquals(6, joinedArray.length); assertEquals( "[1, 2, 3, 4, 5, 6]" , Arrays.toString(joinedArray)); } @Test public void join_two_String_arrays() { String[] int1 = new String[] { "Dog", "Cat", "Bird" }; String[] int2 = new String[] { "Bird", "Cow" }; String[] joinedArray = testObject.concat(int1, int2); assertEquals(5, joinedArray.length); assertEquals( "[Dog, Cat, Bird, Bird, Cow]" , Arrays.toString(joinedArray)); } @Test public void join_two_SimpleData_Arrays() { SimpleData[] data1 = {new SimpleData("Mary", 30), new SimpleData("Tom", 40)}; SimpleData[] data2 = {new SimpleData("Bob", 18), new SimpleData("John", 60)}; SimpleData[] joinedArray = testObject.concat(data1, data2); assertEquals(4, joinedArray.length); Arrays.stream(joinedArray).forEach(e->System.out.println(e.toString())); } }
5. Java 8 Join Arrays – Summary
In this article, I demonstrated how to join two arrays via System.arraycopy
and Stream
operations: concat
, of
, flatmap
, and toArray
.
6. Download the Source Code
This tutorial consists of a Maven project which includes three Java classes as well as their test classes to join two arrays.
You can download the full source code of this example here: Java 8 Join Arrays Example