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.oforArrays.stream. - Joining two streams: with
concatorflatMap. - Using
toArrayon 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.arraycopyand 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
