How can I concatenate two arrays in Java?
Solution 1
I found a one-line solution from the good old Apache Commons Lang library.
ArrayUtils.addAll(T[], T...)
Code:
String[] both = ArrayUtils.addAll(first, second);
Solution 2
Here's a simple method that will concatenate two arrays and return the result:
public <T> T[] concatenate(T[] a, T[] b) {
int aLen = a.length;
int bLen = b.length;
@SuppressWarnings("unchecked")
T[] c = (T[]) Array.newInstance(a.getClass().getComponentType(), aLen + bLen);
System.arraycopy(a, 0, c, 0, aLen);
System.arraycopy(b, 0, c, aLen, bLen);
return c;
}
Note that it will not work with primitive data types, only with object types.
The following slightly more complicated version works with both object and primitive arrays. It does this by using T
instead of T[]
as the argument type.
It also makes it possible to concatenate arrays of two different types by picking the most general type as the component type of the result.
public static <T> T concatenate(T a, T b) {
if (!a.getClass().isArray() || !b.getClass().isArray()) {
throw new IllegalArgumentException();
}
Class<?> resCompType;
Class<?> aCompType = a.getClass().getComponentType();
Class<?> bCompType = b.getClass().getComponentType();
if (aCompType.isAssignableFrom(bCompType)) {
resCompType = aCompType;
} else if (bCompType.isAssignableFrom(aCompType)) {
resCompType = bCompType;
} else {
throw new IllegalArgumentException();
}
int aLen = Array.getLength(a);
int bLen = Array.getLength(b);
@SuppressWarnings("unchecked")
T result = (T) Array.newInstance(resCompType, aLen + bLen);
System.arraycopy(a, 0, result, 0, aLen);
System.arraycopy(b, 0, result, aLen, bLen);
return result;
}
Here is an example:
Assert.assertArrayEquals(new int[] { 1, 2, 3 }, concatenate(new int[] { 1, 2 }, new int[] { 3 }));
Assert.assertArrayEquals(new Number[] { 1, 2, 3f }, concatenate(new Integer[] { 1, 2 }, new Number[] { 3f }));
Solution 3
Using Stream
in Java 8:
String[] both = Stream.concat(Arrays.stream(a), Arrays.stream(b))
.toArray(String[]::new);
Or like this, using flatMap
:
String[] both = Stream.of(a, b).flatMap(Stream::of)
.toArray(String[]::new);
To do this for a generic type you have to use reflection:
@SuppressWarnings("unchecked")
T[] both = Stream.concat(Arrays.stream(a), Arrays.stream(b)).toArray(
size -> (T[]) Array.newInstance(a.getClass().getComponentType(), size));
Solution 4
It's possible to write a fully generic version that can even be extended to concatenate any number of arrays. This versions require Java 6, as they use Arrays.copyOf()
Both versions avoid creating any intermediary List
objects and use System.arraycopy()
to ensure that copying large arrays is as fast as possible.
For two arrays it looks like this:
public static <T> T[] concat(T[] first, T[] second) {
T[] result = Arrays.copyOf(first, first.length + second.length);
System.arraycopy(second, 0, result, first.length, second.length);
return result;
}
And for a arbitrary number of arrays (>= 1) it looks like this:
public static <T> T[] concatAll(T[] first, T[]... rest) {
int totalLength = first.length;
for (T[] array : rest) {
totalLength += array.length;
}
T[] result = Arrays.copyOf(first, totalLength);
int offset = first.length;
for (T[] array : rest) {
System.arraycopy(array, 0, result, offset, array.length);
offset += array.length;
}
return result;
}
Solution 5
Or with the beloved Guava:
String[] both = ObjectArrays.concat(first, second, String.class);
Also, there are versions for primitive arrays:
Booleans.concat(first, second)
Bytes.concat(first, second)
Chars.concat(first, second)
Doubles.concat(first, second)
Shorts.concat(first, second)
Ints.concat(first, second)
Longs.concat(first, second)
Floats.concat(first, second)
devlearn
Updated on April 02, 2022Comments
-
devlearn about 2 years
I need to concatenate two
String
arrays in Java.void f(String[] first, String[] second) { String[] both = ??? }
Which is the easiest way to do this?
-
Ben Page about 8 yearsBytes.concat from Guava
-
Artur Opalinski almost 8 yearsI see a lot of responses here but the question is so worded ('easiest way' ?) that it does not allow to indicate the best answer...
-
Douglas Held over 7 yearsDozens of answers here are copying the data into a new array because that is what was asked for - but copying data when not strictly necessary is a bad thing to do especially in Java. Instead, keep track of the indexes and use the two arrays as if they were joined. I have added a solution illustrating the technique.
-
Bill K over 6 yearsThe simplest is that you probably shouldn't be using arrays in the first place, you should be using ArrayLists, and your output should be an ArrayList. Once you've made these your pre-condition, the operation is built-in--first.addAll(second). The only case where this wouldn't be pretty much automatic is when your arrays are non-object types (int, long, double, ...), in that case intrinsic arrays can have a big advantage over ArrayLists--but for Strings--meh
-
JollyJoker over 6 yearsThe fact that a question like this currently has 50 different answers makes me wonder why Java never got a simple
array1 + array2
concatenation. -
rghome about 6 yearsYou can do it perfectly well and very efficiently in two lines of standard Java (see my answer), so there is not an awful lot to be gained by having a single method to do it. All of these weird-and-wonderful solutions are a bit of a waste of time.
-
-
Tim Frey over 15 yearsHad to downvote this one for all the unnecessary List object creation.
-
Dan Dyer over 15 yearsYou can suppress the warning for this method, but other than that there isn't much you can do. Arrays and generics don't really mix.
-
Lorenzo Boccaccia over 15 yearsthis however means that you are returning the same array and changing a value on the returned array changes the value in the same position of the input array returned.
-
volley about 15 yearsYes - see comment at the end of my post regarding array re-usage. The maintenance overhead imposed by this solution was worth it in our particular case, but defensive copying should probably be used in most cases.
-
Joachim Sauer about 15 yearsThe unchecked warning can be eliminated if you use Arrays.copyOf(). See my answer for an implementation.
-
Josh about 15 years@SuppressWarnings("unchecked")
-
palantus almost 15 yearsI still like Joachim Sauer's solution better.
-
Damo almost 15 yearsI'm still on Java 5 so can't use Arrays.copyOf() as Joachim is doing.
-
AdamC almost 15 yearsI agree, this isn't really answering the question. High level libraries can be great, but if you want to learn an efficient way to do it, you want to look at the code the library method is using. Also, in many situations, you can't just through another library in the product on the fly.
-
Adam over 14 yearsI think this is a good answer. POJO solutions have also been provided, but if the OP is using Apache Commons in their program already (altogether possible considering its popularity) he may still not know this solution. Then he wouldn't be "adding a dependency for this one method," but would be making better use of an existing library.
-
Rosdi Kasim almost 14 yearsLorenzo / volley, can you explain which part in the code that cause array re-usage? I thought
System.arraycopy
copies the content of the array? -
volley almost 14 yearsA caller would normally expect a call to concat() to return a newly allocated array. If either a or b is null, concat() will however return one of the arrays passed into it. This re-usage is what may be unexpected. (Yep, arraycopy only does copying. The re-usage comes from returning either a or b directly.)
-
bancer over 13 years+1. It would be better to replace the second
for
loop with that:for(int j = 0; j < arr2.length; j++){arrBoth[arr1.length+j] = arr2[j];}
-
KJW over 13 years@Outlaw Programmer, I think most people would rather have the simplest possible method. Java is verbose enough already.
-
kvn about 13 yearsI like this suggestion since it is less dependent on the latest Java versions. In my projects I'm often stuck using older versions of Java or CLDC profiles where some of the facilities like those mentioned by Antti are not available.
-
Joachim Sauer almost 13 years@djBO: for primitive-typed arrays you'd need to make an overload for each type: just copy the code and replace each
T
withbyte
(and lose the<T>
). -
Johnydep almost 13 yearscan you plese tell me how to use <T> operator type in my class?
-
Martin almost 13 yearsEasy yes. But converting to and from a List does not sound very performant.
-
rektide over 12 yearsGood general idea, but to anyone implementing: I'd prefer a copyOf and non-copyOf versions than one that does both by way of reflection.
-
marathon over 12 yearsI'd add this to the beginning, just to be defensive. if (first == null) { if (second == null) { return null; } return second; } if (second == null) { return first; }
-
Sam Goldberg over 12 years@djBo: what about:
ByteBuffer buffer = ByteBuffer.allocate(array1.length + array2.length); buffer.put(array1); buffer.put(array2); return buffer.array();
-
Leigh about 12 yearsWelcome to stackoverflow. As this question is quite old, and System.arraycopy was thoroughly discussed already, it is best to avoid resurrecting old threads unless the response contributes something significant to the thread.
-
Johnny Lim almost 12 yearsI'm using commons-lang-2.4.jar. There's no generic version of addAll() in ArrayUtils. So I had to cast the returned Object[] to String[] explicitly.
-
ShadowFlame over 11 yearsreworked mine for File[], but it's the same. Thanks for your solution
-
marcorossi about 11 yearsyou could have given the reference to the answer as you did, and pasted the implementation from the source. that would have solved the issues above about the "cheating" aspect of your answer.
-
orique almost 11 yearsTricky, it compiles only if
first
andsecond
are final -
Frimousse almost 11 yearsTrue. I thought it was worth it to add a one-liner without external library.
-
Malcolm almost 11 yearsThe OP asked for the easiest way to solve the problem. This really is the easiest way, but only under the assumption that the library is already present, which is not mentioned in the question. Otherwise it is actually much easier to copy and paste several lines of code instead of copying just one and then messing with adding a separate library to the project.
-
T-Bull almost 11 yearsThere's a bug in this approach which becomes apparent if you invoke these functions with arrays of different component types, for example
concat(ai, ad)
, whereai
isInteger[]
andad
isDouble[]
. (In this case, the type parameter<T>
is resolved to<? extends Number>
by the compiler.) The array created byArrays.copyOf
will have the component type of the first array, i.e.Integer
in this example. When the function is about to copy the second array, anArrayStoreException
will be thrown. The solution is to have an additionalClass<T> type
parameter. -
Ravi Wallau over 10 yearsAs much as I love Guava, the method from Apache Commons deals better with nullables.
-
PhoneixS about 10 yearsSimply, but inefficient as it make an array for ArrayList and then generate another for toArray method. But still valid as it's simple to read.
-
user924272 about 10 yearsWhile it is good to use libraries, it's unfortunate that the problem has been abstracted away. Therefore the underlying solution remains elusive.
-
Sam Goldberg almost 10 years@BrettOkken: yes - you are correct. I don't know why I suggested it... (probably because I had just written code to concatentate byte arrays...)
-
Breno Salgado almost 10 yearsWhats the problem with abstraction? Dunno what's the deal with reinventing the wheel here, if you want to learn the problem the check the source or read on it. Professional code should be using high-level libraries, much better if it's developed inside Google!
-
Jonas Czech about 9 yearsProbably quite inefficient though.
-
Jonas Czech about 9 years..But inefficient and slow.
-
Adriaan Koster about 9 yearsThis is not concatenation but copying. The destination must already have enough space to accommodate all the sources or the above code will cause an ArrayIndexOutOfBoundsException.
-
dragon66 almost 9 yearsThe following line will break the generic part: concatenate(new String[]{"1"},new Object[] { new Object()})
-
Hindol almost 9 yearsIf you are always worried about not adding a library for a single method, no new libraries will ever get added. Given the excellent utilities present in Apache Commons, I highly recommend adding it when the very first use case arises.
-
usr-local-ΕΨΗΕΛΩΝ over 8 yearsFor performance reasons, I would pre-compute the ArrayList's final size because ArrayList, by definition, allocates a new array and copies its elements every time the current array is full. Otherwise I would go straight for LinkedList which does not suffer such problem
-
Tripp Kinetics over 8 yearsYou might want to add
null
checks. And perhaps set some of your variables tofinal
. -
Ky - over 8 yearsHow efficient is this?
-
Synox over 8 yearsWOW nice! why not change the compiler to realize a java syntax problem. :) bold move!
-
Trevor Brown about 8 yearsWorth a read: jaxenter.com/… tl;dr - streams could be performant or not, it depends on what you're doing with them and the constraints of the problem (isn't this always the answer? lol)
-
Marcin Zukowski about 8 yearsYeah, it's a risky solution from the performance point of view. It might be fast, but I wouldn't bet my application's performance on it ;)
-
Kasun Siyambalapitiya almost 8 years@Antti Sykäri sorry for asking I'm a newbie to Java, why is
(String[])
is used inString[] both = (String[])ArrayUtils.addAll(first, second);
without it will it not combine the 2 arrays -
Jeryl Cook almost 8 yearsusing apache commons should never be called 'cheating' i question the sanity of developers who thing its an unnecessary dependency.
-
Will Hardwick-Smith almost 8 yearsAdditionally, if a or b are arrays of primitive types, their streams will need to be
.boxed()
so they are of typeStream
rather than e.g.IntStream
which cannot be passed as a parameter toStream.concat
. -
Abdu over 7 yearsArrayUtils can be downloaded at commons.apache.org/proper/commons-lang/download_lang.cgi
-
Ronen Rabinovici about 7 yearsThe answer is great but a tiny bit broken. To make it perfect you should pass to toArray() an array of the type you need. In the above example, the code should be: both.toArray(new String[0]) See: stackoverflow.com/questions/4042434/…
-
slartidan almost 7 years
myList.addAll(new ArrayList<String>(Arrays.asList(second)));
can be simplified tomyList.addAll(Arrays.asList(second))
-
Holger almost 7 years@Will Hardwick-Smith: no, you only have to pick the right stream class, e.g. if
a
andb
areint[]
, useint[] both = IntStream.concat(Arrays.stream(a), Arrays.stream(b)).toArray();
-
Bill K over 6 yearsGood solution--would be better if the code was refactored to avoid arrays altogether in favor of ArrayLists, but that's outside the control of the "Answer" and up to the questioner.
-
Bill K over 6 yearsI'd sum up the length in the same loop where you are doing your null check--but this is a really good summary of the other answers here. I believe it even handles intrinsic types like "int" without changing them to Integer objects which is really the ONLY reason to deal with them as arrays rather than just changing everything to ArrayLists. Also your method could take 2 arrays and a (...) parameter so the caller knows he needs to pass in at least two arrays before he runs it and sees the error, but that complicates the looping code....
-
drmrbrewer over 6 yearsDon't know why this answer isn't rated higher... though it does seem to need the change suggested by @RonenRabinovici
-
Lii over 6 years@Supuhstar: It is probably not as fast as
System.arrayCopy
. But not particularly slow either. You probably have to do this a very many times with huge arrays in really performance sensitive contexts for the execution time difference to matter. -
Honza over 6 yearsOr better, without unnecessary allocation of zero-length array:
both.toArray(new String[both.size()])
;) -
Sébastien Tromp over 6 years@RaviWallau Could you link to the class that does this?
-
Ravi Wallau over 6 years@SébastienTromp It is the top solution for this question - ArrayUtils.
-
joro about 6 yearsapplicable for Strings and objects (as question wants), but there is no addAll method for primary types (as ints)
-
Sina Madani about 6 yearsI wonder which is faster and more memory efficient: the concat method or flatMap? Or are they the same under the hood?
-
Rudra about 6 yearsWaste of CPU & Memory. See the answer from @Douglas-Held
-
Dave L. about 6 yearsThe latter solution is nice because it can be used for more than 2 arrays unlike most (if not all) the other answers.
-
rghome about 6 yearsThis is the same as a previous answer 10 Feb 16.
-
rghome almost 6 yearsI count that it requires 4 additional temporary objects to work.
-
beaudet over 5 yearswould be nice not to have to use the @SuppressWarnings annotation - I'll post a solution for that below.
-
John over 5 yearsUse
String[] arrBoth = java.util.Arrays.copyOf(arr1, arr1.length + arr2.length)
to skip the firstfor
loop. Saves time proportional to size ofarr1
. -
Holger about 5 years@SinaMadani with all known implementations, the variant using
concat
will be faster and need less memory, because it can predict the resulting array size beforehand and will create and fill only one array. In contrast, theflatMap
based solution will have to use a resizable buffer internally, with at least one final copying step. -
Holger about 5 yearsAs elaborated in this article, using
both.toArray(new String[0])
will be faster thanboth.toArray(new String[both.size()])
, even if it contradicts our naive intuition. That’s why it is so important to measure the actual performance when optimizing. Or just use the simpler construct, when the advantage of the more complicated variant can’t be proven. -
Holger about 5 years@Honza recommended read
-
Maarten Bodewes about 5 yearsCode should be as much self explanatory as possible. People reading the code should not have to lookup the JavaDoc of a called function to find out that it does one thing for one particular condition and something else for another. In short: you can generally not fix design problems like these with a comment. Just leaving the two
if
statements out would be the easiest fix. -
volley about 5 years@MaartenBodewes I agree. This method was used at a very specific location to fix a very specific problem identified using profiling. I'll edit the comment about JavaDoc.
-
jpmc26 about 5 years@OutlawProgrammer I rarely hesitate to add a dependency to my application if it makes the code simpler and means I have less to maintain. Most people don't work under the kinds of constraints that necessitate worrying about adding a dependency. (I.e., they have plenty of disk space, don't need the absolutely fastest in everything, etc.)
-
Maarten Bodewes about 5 yearsAn if statement per copy is not a brilliant idea as it will have a hefty performance hit.
-
Maarten Bodewes about 5 yearsThat's very convoluted, hard to understand, undocumented and - with two if statements in the loop - rather inefficient as well.
-
Maarten Bodewes about 5 years
resutlentArray
?addTwoArray
? Hard to read code and YouTube style comments !!! -
Maarten Bodewes about 5 yearsThis seems like useful code and catches both objects and base types. I would however not call a function
resizeArray
because arrays cannot be resized in Java. This is whyArrays.copyOf
does the same thing, but with a different method name. -
c-chavez about 5 years@MaartenBodewes it's always nice to learn new approaches focused on performance. Any suggestions to improve this?
-
Maarten Bodewes about 5 yearsWell, yes,
arrayCopy
but I guess that's mentioned in quite a few other examples. Same for two or morefor
loops; it is possible to bring the branching (the if statements) out of the loop. -
Maarten Bodewes about 5 years@rghome You can link to answers by hitting the share button. Basic, why not remove the answer if there is a clear dupe of an earlier date? If you want you can improve the existing one, if anything is missing there.
-
Maarten Bodewes about 5 years@TrippKinetics
null
checks would hide NPE's rather than showing them and using final for local vars doesn't have any benefit (yet). -
Maarten Bodewes about 5 yearsPersonally I would use normal
for
loops with an index rather thanfor-each
here. It's unlikely to the extreme that this will be refactored to using lists (you'd just write another method) and for-each will very likely be slower than direct array access through indexing. Nitpick:pos
should be defined within the scope firstfor
loop, not outside it. -
spacebiker about 5 yearsNot really, copyOf just makes a copy with the same length, if you read the code carefully, you will realize that the function receives the parameter
newSize
so resizeArray does just that, returns a resized array. -
rghome about 5 years@Maarten Bodewes I think you will find (if you benchmark it, which I have) that the for-each runs in the same time as the indexed loop on late versions of Java. The optimizer takes care of it.
-
mjs almost 5 yearsTry using that on char[] = {'a'} :/
-
Artsiom Chapialiou almost 5 yearsIs it possible to make it works for generic type (like in the answer above)? Something like
T[] both = Stream.of(a, b).flatMap(Stream::of).toArray(T[]::new);
Looks likeT[]::new
isn't allowed cause of type erasure... -
Blake almost 5 years+1 for
Array.newInstance(a.getClass().getComponentType(), aLen + bLen);
. I've surprisingly never seen that before. @beaudet I think the annotation is fine here, considering why it is being suppressed. -
beaudet almost 5 yearsha, call me a purist but I prefer clean code that doesn't require suppression of warnings in order to remove warnings
-
Melih over 4 yearsThese kind of solutions are helping to people working alone on their hobby projects but has no contribution when you are working on a company project or basically a project you just should not add a new dependency to concat two arrays.
-
Lii over 4 years@ArtsiomChapialiou: You can, but it's not so pretty. You have to use reflection to create the array, and thus get an unchecked cast. I added that to the solution text.
-
Farid about 4 years@rghome, at least it doesn't require additional library to implement such simple task
-
Stephen J about 4 yearsThere's a difference between semantic warnings and "I'm using raw memory like I would in C, so turn off your safety since I know what I'm doing" "I'm being unsafe" isn't a semantic warning suppression. It's a "I'm going lower level on purpose now, so stop whining." Feel lucky, as Swift 5 removed suppressors. Java, unlike Swift, is still made for programmers who aren't afraid of doing their own programming
-
jumping_monkey about 4 yearsHi @Honza, possible to do the same to return a primitive integer array in 3 lines?
-
Shebla Tsama about 4 yearsThis is one of the best solutions. 100% standard Java. Fast/efficient. Should get more upvotes!
-
alexovits almost 4 yearsDefinitely the best solution.
-
Satish Patro over 3 yearsOne doubt, can it handle null, like if null is there response is null or blank string arr if other one is blank?
-
gouessej over 3 yearsI don't advise to add Guava into a project only to concatenate arrays, it's big and it has a serious lack of modularity. @BrenoSalgado "much better if it's developed inside Google" I strongly disagree with that.
-
Mr00Anderson over 3 yearsThis should not be the number one answer. The answer using a external library for something so trivial is overkill.
-
javalearner_heaven over 3 yearsThis must be the accepted answer "the more efficient"
-
XYZ about 3 years@JohnnyLim, how do you cast the Object[] to String[] when using
ArrayUtils.addAll(Arr1, Arr2)
? My Arr1 / Arr2 is initialized asList<Object> obj = new ArrayList<>()
, with content from double, string etc. -
Lakshitha Kanchana almost 3 yearsYes, this is the best solution. Should have more up votes.
-
Barracuda almost 3 yearsThe second version does not work with an array of strings as it's first and an array of long (primitives) as it's second.
-
Robert about 2 yearsIt's crazy that the JDK doesn't have a method like this.
-
M. Justin about 2 years@RaviWallau Of course, the Guava nullability behavior is by design, so it really depends on whether you're trying to avoid
null
s or not, and whether it would be an error for the calling site to see anull
in the first place. "For [reasons mentioned on the linked page], many of Guava's utilities are designed to fail fast in the presence of null rather than allow nulls to be used, so long as there is a null-friendly workaround available."