1572

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?

Dan
  • 3,647
  • 5
  • 20
  • 26
Antti Kissaniemi
  • 18,944
  • 13
  • 54
  • 47
  • 4
    Bytes.concat from Guava – Ben Page Mar 15 '16 at 11:27
  • 2
    I see a lot of responses here but the question is so worded ('easiest way' ?) that it does not allow to indicate the best answer... – Artur Opalinski May 15 '16 at 03:36
  • 3
    Dozens 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. – Douglas Held Sep 04 '16 at 23:34
  • 1
    The 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 – Bill K Aug 15 '17 at 16:27
  • 47
    The fact that a question like this currently has 50 different answers makes me wonder why Java never got a simple `array1 + array2` concatenation. – JollyJoker Nov 28 '17 at 12:53
  • 2
    You 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. – rghome Apr 11 '18 at 13:16
  • Such questions just remind you how bad is java with array and collection manipulations in general.. – ACV Mar 27 '23 at 15:13

66 Answers66

1271

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);
Community
  • 1
  • 1
Antti Kissaniemi
  • 18,944
  • 13
  • 54
  • 47
  • 203
    How is it "cheating" if it answers the question? Sure, having an extra dependency is probably overkill for this specific situation, but no harm is done in calling out that it exists, especially since there's so many excellent bits of functionality in Apache Commons. – Rob Oct 12 '08 at 15:58
  • 40
    I 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. – AdamC Jun 18 '09 at 17:09
  • 88
    I 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. – Adam Nov 17 '09 at 15:36
  • 3
    @Outlaw Programmer, I think most people would rather have the simplest possible method. Java is verbose enough already. – KJW Nov 26 '10 at 22:35
  • 3
    I'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. – Johnny Lim May 17 '12 at 11:33
  • you 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. – marcorossi May 03 '13 at 15:33
  • 4
    The 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. – Malcolm Jul 12 '13 at 21:51
  • 19
    If 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. – Hindol Jun 25 '15 at 08:46
  • 1
    @Antti Sykäri sorry for asking I'm a newbie to Java, why is `(String[])` is used in `String[] both = (String[])ArrayUtils.addAll(first, second);` without it will it not combine the 2 arrays – Kasun Siyambalapitiya Jun 06 '16 at 07:41
  • 11
    using apache commons should never be called 'cheating' i question the sanity of developers who thing its an unnecessary dependency. – Jeryl Cook Jul 05 '16 at 20:06
  • ArrayUtils can be downloaded at http://commons.apache.org/proper/commons-lang/download_lang.cgi – Abdu Aug 11 '16 at 07:36
  • 2
    @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.) – jpmc26 Mar 21 '19 at 03:41
  • These 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. – Melih Sep 25 '19 at 16:38
  • One doubt, can it handle null, like if null is there response is null or blank string arr if other one is blank? – Satish Patro Aug 05 '20 at 11:59
  • 1
    This should not be the number one answer. The answer using a external library for something so trivial is overkill. – Mr00Anderson Sep 10 '20 at 13:39
  • @JohnnyLim, how do you cast the Object[] to String[] when using `ArrayUtils.addAll(Arr1, Arr2)`? My Arr1 / Arr2 is initialized as `List obj = new ArrayList<>()`, with content from double, string etc. – XYZ Mar 04 '21 at 12:25
790

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 }));
joshkmartinez
  • 654
  • 1
  • 12
  • 35
jeannicolas
  • 3,139
  • 4
  • 24
  • 25
  • 1
    I 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. – kvn Feb 07 '11 at 15:46
  • 4
    The following line will break the generic part: concatenate(new String[]{"1"},new Object[] { new Object()}) – dragon66 Jun 03 '15 at 02:09
  • would be nice not to have to use the @SuppressWarnings annotation - I'll post a solution for that below. – beaudet Nov 06 '18 at 22:57
  • +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. – Blake Jun 26 '19 at 20:12
  • 2
    ha, call me a purist but I prefer clean code that doesn't require suppression of warnings in order to remove warnings – beaudet Jun 27 '19 at 21:18
  • 1
    There'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 – Stephen J Feb 05 '20 at 20:35
  • The second version does not work with an array of strings as it's first and an array of long (primitives) as it's second. – Barracuda Aug 02 '21 at 21:09
585

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));
Lii
  • 11,553
  • 8
  • 64
  • 88
Vitalii Fedorenko
  • 110,878
  • 29
  • 149
  • 111
  • 45
    How efficient is this? – Ky - Oct 02 '15 at 01:34
  • 12
    Worth a read: https://jaxenter.com/java-performance-tutorial-how-fast-are-the-java-8-streams-118830.html 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) – Trevor Brown Feb 25 '16 at 17:29
  • Yeah, 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 ;) – Marcin Zukowski Apr 07 '16 at 23:21
  • 6
    Additionally, if *a* or *b* are arrays of primitive types, their streams will need to be `.boxed()` so they are of type `Stream` rather than e.g. `IntStream` which cannot be passed as a parameter to `Stream.concat`. – Will Hardwick-Smith Jul 16 '16 at 09:59
  • 30
    @Will Hardwick-Smith: no, you only have to pick the right stream class, e.g. if `a` and `b` are `int[]`, use `int[] both = IntStream.concat(Arrays.stream(a), Arrays.stream(b)).toArray();` – Holger Jun 13 '17 at 12:28
  • 7
    @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. – Lii Dec 23 '17 at 15:43
  • I wonder which is faster and more memory efficient: the concat method or flatMap? Or are they the same under the hood? – Sina Madani Apr 06 '18 at 11:00
  • 1
    The latter solution is nice because it can be used for more than 2 arrays unlike most (if not all) the other answers. – Dave L. Apr 09 '18 at 19:51
  • 2
    @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, the `flatMap` based solution will have to use a resizable buffer internally, with at least one final copying step. – Holger Feb 25 '19 at 15:15
  • Is 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 like `T[]::new` isn't allowed cause of type erasure... – Artsiom Chapialiou Jun 18 '19 at 16:55
  • 1
    @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. – Lii Dec 17 '19 at 09:20
499

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;
}
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • 11
    @djBO: for primitive-typed arrays you'd need to make an overload for each type: just copy the code and replace each `T` with `byte` (and lose the ``). – Joachim Sauer Jun 01 '11 at 06:01
  • can you plese tell me how to use operator type in my class? – Johnydep Jun 27 '11 at 02:22
  • 6
    I'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; } – marathon Sep 22 '11 at 04:18
  • 5
    @djBo: what about:`ByteBuffer buffer = ByteBuffer.allocate(array1.length + array2.length); buffer.put(array1); buffer.put(array2); return buffer.array();` – Sam Goldberg Dec 02 '11 at 15:29
  • 25
    There'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)`, where `ai` is `Integer[]` and `ad` is `Double[]`. (In this case, the type parameter `` is resolved to ` extends Number>` by the compiler.) The array created by `Arrays.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, an `ArrayStoreException` will be thrown. The solution is to have an additional `Class type` parameter. – T-Bull Jul 25 '13 at 17:16
  • @BrettOkken: yes - you are correct. I don't know why I suggested it... (probably because I had just written code to concatentate byte arrays...) – Sam Goldberg Jun 27 '14 at 16:09
205

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)
Steve Chambers
  • 37,270
  • 24
  • 156
  • 208
KARASZI István
  • 30,900
  • 8
  • 101
  • 128
  • As much as I love Guava, the method from Apache Commons deals better with nullables. – Ravi Wallau Nov 01 '13 at 19:19
  • 7
    While it is good to use libraries, it's unfortunate that the problem has been abstracted away. Therefore the underlying solution remains elusive. – KRK Owner Apr 09 '14 at 00:15
  • 54
    Whats 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! – Breno Salgado Jul 15 '14 at 20:11
  • @RaviWallau Could you link to the class that does this? – Sébastien Tromp Jan 12 '18 at 14:48
  • 1
    @SébastienTromp It is the top solution for this question - ArrayUtils. – Ravi Wallau Jan 13 '18 at 04:45
  • 3
    I 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. – gouessej Aug 05 '20 at 12:17
  • It's crazy that the JDK doesn't have a method like this. – Robert Feb 12 '22 at 04:05
  • @RaviWallau Of course, the Guava nullability behavior is [by design](https://github.com/google/guava/wiki/UsingAndAvoidingNullExplained), 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 a `null` 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." – M. Justin Apr 26 '22 at 16:49
174

You can append the two arrays in two lines of code.

String[] both = Arrays.copyOf(first, first.length + second.length);
System.arraycopy(second, 0, both, first.length, second.length);

This is a fast and efficient solution and will work for primitive types as well as the two methods involved are overloaded.

You should avoid solutions involving ArrayLists, streams, etc as these will need to allocate temporary memory for no useful purpose.

You should avoid for loops for large arrays as these are not efficient. The built in methods use block-copy functions that are extremely fast.

rghome
  • 8,529
  • 8
  • 43
  • 62
59

Using the Java API:

String[] f(String[] first, String[] second) {
    List<String> both = new ArrayList<String>(first.length + second.length);
    Collections.addAll(both, first);
    Collections.addAll(both, second);
    return both.toArray(new String[both.size()]);
}
Fabian Steeg
  • 44,988
  • 7
  • 85
  • 112
  • 17
    Simply, 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. – PhoneixS Mar 10 '14 at 12:16
  • 1
    applicable for Strings and objects (as question wants), but there is no addAll method for primary types (as ints) – JRr Mar 23 '18 at 07:20
  • 1
    As elaborated in [this article](https://shipilev.net/blog/2016/arrays-wisdom-ancients/), using `both.toArray(new String[0])` will be faster than `both.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 Feb 25 '19 at 15:19
43

A solution 100% old java and without System.arraycopy (not available in GWT client for example):

static String[] concat(String[]... arrays) {
    int length = 0;
    for (String[] array : arrays) {
        length += array.length;
    }
    String[] result = new String[length];
    int pos = 0;
    for (String[] array : arrays) {
        for (String element : array) {
            result[pos] = element;
            pos++;
        }
    }
    return result;
}
deem
  • 1,252
  • 1
  • 19
  • 38
francois
  • 11
  • 2
  • 3
  • reworked mine for File[], but it's the same. Thanks for your solution – ShadowFlame Sep 07 '12 at 10:49
  • 5
    Probably quite inefficient though. – Jonas Czech Apr 11 '15 at 20:34
  • You might want to add `null` checks. And perhaps set some of your variables to `final`. – Tripp Kinetics Sep 24 '15 at 14:31
  • @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 Mar 24 '19 at 13:22
  • Personally I would use normal `for` loops with an index rather than `for-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 first `for` loop, not outside it. – Maarten Bodewes Mar 24 '19 at 13:24
  • 2
    @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. – rghome Mar 28 '19 at 07:46
34

I've recently fought problems with excessive memory rotation. If a and/or b are known to be commonly empty, here is another adaption of silvertab's code (generified too):

private static <T> T[] concatOrReturnSame(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;
}

Edit: A previous version of this post stated that array re-usage like this shall be clearly documented. As Maarten points out in the comments it would in general be better to just remove the if statements, thus voiding the need for having documentation. But then again, those if statements were the whole point of this particular optimization in the first place. I'll leave this answer here, but be wary!

volley
  • 6,651
  • 1
  • 27
  • 28
  • 5
    this 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. – Lorenzo Boccaccia Nov 26 '08 at 17:55
  • Yes - 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. – volley Mar 17 '09 at 14:43
  • Lorenzo / volley, can you explain which part in the code that cause array re-usage? I thought `System.arraycopy` copies the content of the array? – Rosdi Kasim May 13 '10 at 02:35
  • 4
    A 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.) – volley May 14 '10 at 06:57
  • Code 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. – Maarten Bodewes Mar 18 '19 at 15:25
  • @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. – volley Mar 20 '19 at 20:32
  • Try using that on char[] = {'a'} :/ – mjs Jun 10 '19 at 07:18
27
ArrayList<String> both = new ArrayList(Arrays.asList(first));
both.addAll(Arrays.asList(second));

both.toArray(new String[0]);
h-rai
  • 3,636
  • 6
  • 52
  • 76
  • 3
    The 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: http://stackoverflow.com/questions/4042434/converting-arrayliststring-to-string-in-java – Ronen Rabinovici Feb 15 '17 at 20:12
  • Don't know why this answer isn't rated higher... though it does seem to need the change suggested by @RonenRabinovici – drmrbrewer Dec 02 '17 at 11:14
  • 4
    Or better, without unnecessary allocation of zero-length array: `both.toArray(new String[both.size()])` ;) – Honza Jan 10 '18 at 16:42
  • 2
    @Honza [recommended read](https://shipilev.net/blog/2016/arrays-wisdom-ancients/) – Holger Feb 25 '19 at 15:20
  • Hi @Honza, possible to do the same to return a primitive integer array in 3 lines? – jumping_monkey Feb 10 '20 at 00:40
27

The Functional Java library has an array wrapper class that equips arrays with handy methods like concatenation.

import static fj.data.Array.array;

...and then

Array<String> both = array(first).append(array(second));

To get the unwrapped array back out, call

String[] s = both.array();
Apocalisp
  • 34,834
  • 8
  • 106
  • 155
20

Another way with Java8 using Stream

  public String[] concatString(String[] a, String[] b){ 
    Stream<String> streamA = Arrays.stream(a);
    Stream<String> streamB = Arrays.stream(b);
    return Stream.concat(streamA, streamB).toArray(String[]::new); 
  }
Vaseph
  • 704
  • 1
  • 8
  • 20
17

Here's an adaptation of silvertab's solution, with generics retrofitted:

static <T> T[] concat(T[] a, T[] b) {
    final int alen = a.length;
    final int blen = b.length;
    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;
}

NOTE: See Joachim's answer for a Java 6 solution. Not only does it eliminate the warning; it's also shorter, more efficient and easier to read!

Community
  • 1
  • 1
volley
  • 6,651
  • 1
  • 27
  • 28
15

You could try converting it into a ArrayList and use the addAll method then convert back to an array.

List list = new ArrayList(Arrays.asList(first));
  list.addAll(Arrays.asList(second));
  String[] both = list.toArray();
Guy Avraham
  • 3,482
  • 3
  • 38
  • 50
Paul
  • 670
  • 7
  • 19
  • Good 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 Aug 15 '17 at 16:29
  • I count that it requires 4 additional temporary objects to work. – rghome Jul 25 '18 at 07:31
  • 2
    @rghome, at least it doesn't require additional library to implement such simple task – Farid Feb 03 '20 at 12:33
13

If you use this way so you no need to import any third party class.

If you want concatenate String

Sample code for concate two String Array

public static String[] combineString(String[] first, String[] second){
        int length = first.length + second.length;
        String[] result = new String[length];
        System.arraycopy(first, 0, result, 0, first.length);
        System.arraycopy(second, 0, result, first.length, second.length);
        return result;
    }

If you want concatenate Int

Sample code for concate two Integer Array

public static int[] combineInt(int[] a, int[] b){
        int length = a.length + b.length;
        int[] result = new int[length];
        System.arraycopy(a, 0, result, 0, a.length);
        System.arraycopy(b, 0, result, a.length, b.length);
        return result;
    }

Here is Main method

    public static void main(String[] args) {

            String [] first = {"a", "b", "c"};
            String [] second = {"d", "e"};

            String [] joined = combineString(first, second);
            System.out.println("concatenated String array : " + Arrays.toString(joined));

            int[] array1 = {101,102,103,104};
            int[] array2 = {105,106,107,108};
            int[] concatenateInt = combineInt(array1, array2);

            System.out.println("concatenated Int array : " + Arrays.toString(concatenateInt));

        }
    }  

We can use this way also.

Raj Rusia
  • 728
  • 10
  • 15
12

Please forgive me for adding yet another version to this already long list. I looked at every answer and decided that I really wanted a version with just one parameter in the signature. I also added some argument checking to benefit from early failure with sensible info in case of unexpected input.

@SuppressWarnings("unchecked")
public static <T> T[] concat(T[]... inputArrays) {
  if(inputArrays.length < 2) {
    throw new IllegalArgumentException("inputArrays must contain at least 2 arrays");
  }

  for(int i = 0; i < inputArrays.length; i++) {
    if(inputArrays[i] == null) {
      throw new IllegalArgumentException("inputArrays[" + i + "] is null");
    }
  }

  int totalLength = 0;

  for(T[] array : inputArrays) {
    totalLength += array.length;
  }

  T[] result = (T[]) Array.newInstance(inputArrays[0].getClass().getComponentType(), totalLength);

  int offset = 0;

  for(T[] array : inputArrays) {
    System.arraycopy(array, 0, result, offset, array.length);

    offset += array.length;
  }

  return result;
}
Reto Höhener
  • 5,419
  • 4
  • 39
  • 79
  • I'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.... – Bill K Aug 15 '17 at 16:34
11

Using Java 8+ streams you can write the following function:

private static String[] concatArrays(final String[]... arrays) {
    return Arrays.stream(arrays)
         .flatMap(Arrays::stream)
         .toArray(String[]::new);
}
keisar
  • 5,266
  • 5
  • 28
  • 28
9

This should be one-liner.

public String [] concatenate (final String array1[], final String array2[])
{
    return Stream.concat(Stream.of(array1), Stream.of(array2)).toArray(String[]::new);
}
avigaild
  • 73
  • 1
  • 2
  • 6
7

This works, but you need to insert your own error checking.

public class StringConcatenate {

    public static void main(String[] args){

        // Create two arrays to concatenate and one array to hold both
        String[] arr1 = new String[]{"s","t","r","i","n","g"};
        String[] arr2 = new String[]{"s","t","r","i","n","g"};
        String[] arrBoth = new String[arr1.length+arr2.length];

        // Copy elements from first array into first part of new array
        for(int i = 0; i < arr1.length; i++){
            arrBoth[i] = arr1[i];
        }

        // Copy elements from second array into last part of new array
        for(int j = arr1.length;j < arrBoth.length;j++){
            arrBoth[j] = arr2[j-arr1.length];
        }

        // Print result
        for(int k = 0; k < arrBoth.length; k++){
            System.out.print(arrBoth[k]);
        }

        // Additional line to make your terminal look better at completion!
        System.out.println();
    }
}

It's probably not the most efficient, but it doesn't rely on anything other than Java's own API.

Radiodef
  • 37,180
  • 14
  • 90
  • 125
glue
  • 95
  • 2
  • 6
  • 2
    +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];}` – bancer Oct 28 '10 at 21:23
  • Use `String[] arrBoth = java.util.Arrays.copyOf(arr1, arr1.length + arr2.length)` to skip the first `for` loop. Saves time proportional to size of `arr1`. – John Dec 27 '18 at 19:20
7

Here a possible implementation in working code of the pseudo code solution written by silvertab.

Thanks silvertab!

public class Array {

   public static <T> T[] concat(T[] a, T[] b, ArrayBuilderI<T> builder) {
      T[] c = builder.build(a.length + b.length);
      System.arraycopy(a, 0, c, 0, a.length);
      System.arraycopy(b, 0, c, a.length, b.length);
      return c;
   }
}

Following next is the builder interface.

Note: A builder is necessary because in java it is not possible to do

new T[size]

due to generic type erasure:

public interface ArrayBuilderI<T> {

   public T[] build(int size);
}

Here a concrete builder implementing the interface, building a Integer array:

public class IntegerArrayBuilder implements ArrayBuilderI<Integer> {

   @Override
   public Integer[] build(int size) {
      return new Integer[size];
   }
}

And finally the application / test:

@Test
public class ArrayTest {

   public void array_concatenation() {
      Integer a[] = new Integer[]{0,1};
      Integer b[] = new Integer[]{2,3};
      Integer c[] = Array.concat(a, b, new IntegerArrayBuilder());
      assertEquals(4, c.length);
      assertEquals(0, (int)c[0]);
      assertEquals(1, (int)c[1]);
      assertEquals(2, (int)c[2]);
      assertEquals(3, (int)c[3]);
   }
}
hpgisler
  • 125
  • 2
  • 6
6

Wow! lot of complex answers here including some simple ones that depend on external dependencies. how about doing it like this:

String [] arg1 = new String{"a","b","c"};
String [] arg2 = new String{"x","y","z"};

ArrayList<String> temp = new ArrayList<String>();
temp.addAll(Arrays.asList(arg1));
temp.addAll(Arrays.asList(arg2));
String [] concatedArgs = temp.toArray(new String[arg1.length+arg2.length]);
doles
  • 558
  • 6
  • 20
6

A generic static version that uses the high performing System.arraycopy without requiring a @SuppressWarnings annotation:

public static <T> T[] arrayConcat(T[] a, T[] b) {
    T[] both = Arrays.copyOf(a, a.length + b.length);
    System.arraycopy(b, 0, both, a.length, b.length);
    return both;
}
beaudet
  • 886
  • 1
  • 10
  • 13
5

A simple variation allowing the joining of more than one array:

public static String[] join(String[]...arrays) {

    final List<String> output = new ArrayList<String>();

    for(String[] array : arrays) {
        output.addAll(Arrays.asList(array));
    }

    return output.toArray(new String[output.size()]);
}
Radiodef
  • 37,180
  • 14
  • 90
  • 125
Damo
  • 11,410
  • 5
  • 57
  • 74
5

This is a converted function for a String array:

public String[] mergeArrays(String[] mainArray, String[] addArray) {
    String[] finalArray = new String[mainArray.length + addArray.length];
    System.arraycopy(mainArray, 0, finalArray, 0, mainArray.length);
    System.arraycopy(addArray, 0, finalArray, mainArray.length, addArray.length);

    return finalArray;
}
Oritm
  • 2,113
  • 2
  • 25
  • 40
5

How about simply

public static class Array {

    public static <T> T[] concat(T[]... arrays) {
        ArrayList<T> al = new ArrayList<T>();
        for (T[] one : arrays)
            Collections.addAll(al, one);
        return (T[]) al.toArray(arrays[0].clone());
    }
}

And just do Array.concat(arr1, arr2). As long as arr1 and arr2 are of the same type, this will give you another array of the same type containing both arrays.

Radiodef
  • 37,180
  • 14
  • 90
  • 125
Ephraim
  • 2,234
  • 1
  • 21
  • 18
  • 1
    For 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 – usr-local-ΕΨΗΕΛΩΝ Aug 20 '15 at 08:07
4

Another way to think about the question. To concatenate two or more arrays, one have to do is to list all elements of each arrays, and then build a new array. This sounds like create a List<T> and then calls toArray on it. Some other answers uses ArrayList, and that's fine. But how about implement our own? It is not hard:

private static <T> T[] addAll(final T[] f, final T...o){
    return new AbstractList<T>(){

        @Override
        public T get(int i) {
            return i>=f.length ? o[i - f.length] : f[i];
        }

        @Override
        public int size() {
            return f.length + o.length;
        }

    }.toArray(f);
}

I believe the above is equivalent to solutions that uses System.arraycopy. However I think this one has its own beauty.

Earth Engine
  • 10,048
  • 5
  • 48
  • 78
4

How about :

public String[] combineArray (String[] ... strings) {
    List<String> tmpList = new ArrayList<String>();
    for (int i = 0; i < strings.length; i++)
        tmpList.addAll(Arrays.asList(strings[i]));
    return tmpList.toArray(new String[tmpList.size()]);
}
4

Here is the code by abacus-common.

String[] a = {"a", "b", "c"};
String[] b = {"1", "2", "3"};
String[] c = N.concat(a, b); // c = ["a", "b", "c", "1", "2", "3"]

// N.concat(...) is null-safety.
a = null;
c = N.concat(a, b); // c = ["1", "2", "3"]
user_3380739
  • 1
  • 14
  • 14
4
public String[] concat(String[]... arrays)
{
    int length = 0;
    for (String[] array : arrays) {
        length += array.length;
    }
    String[] result = new String[length];
    int destPos = 0;
    for (String[] array : arrays) {
        System.arraycopy(array, 0, result, destPos, array.length);
        destPos += array.length;
    }
    return result;
}
Sujay
  • 2,198
  • 23
  • 32
4

This is probably the only generic and type-safe way:

public class ArrayConcatenator<T> {
    private final IntFunction<T[]> generator;

    private ArrayConcatenator(IntFunction<T[]> generator) {
        this.generator = generator;
    }

    public static <T> ArrayConcatenator<T> concat(IntFunction<T[]> generator) {
        return new ArrayConcatenator<>(generator);
    }

    public T[] apply(T[] array1, T[] array2) {
        T[] array = generator.apply(array1.length + array2.length);
        System.arraycopy(array1, 0, array, 0, array1.length);
        System.arraycopy(array2, 0, array, array1.length, array2.length);
        return array;
    }
}

And the usage is quite concise:

Integer[] array1 = { 1, 2, 3 };
Double[] array2 = { 4.0, 5.0, 6.0 };
Number[] array = concat(Number[]::new).apply(array1, array2);

(requires static import)

Invalid array types are rejected:

concat(String[]::new).apply(array1, array2); // error
concat(Integer[]::new).apply(array1, array2); // error
ZhekaKozlov
  • 36,558
  • 20
  • 126
  • 155
4

Here's my slightly improved version of Joachim Sauer's concatAll. It can work on Java 5 or 6, using Java 6's System.arraycopy if it's available at runtime. This method (IMHO) is perfect for Android, as it work on Android <9 (which doesn't have System.arraycopy) but will use the faster method if possible.

  public static <T> T[] concatAll(T[] first, T[]... rest) {
    int totalLength = first.length;
    for (T[] array : rest) {
      totalLength += array.length;
    }
    T[] result;
    try {
      Method arraysCopyOf = Arrays.class.getMethod("copyOf", Object[].class, int.class);
      result = (T[]) arraysCopyOf.invoke(null, first, totalLength);
    } catch (Exception e){
      //Java 6 / Android >= 9 way didn't work, so use the "traditional" approach
      result = (T[]) java.lang.reflect.Array.newInstance(first.getClass().getComponentType(), totalLength);
      System.arraycopy(first, 0, result, 0, first.length);
    }
    int offset = first.length;
    for (T[] array : rest) {
      System.arraycopy(array, 0, result, offset, array.length);
      offset += array.length;
    }
    return result;
  }
candrews
  • 1,995
  • 1
  • 16
  • 13
  • 1
    Good general idea, but to anyone implementing: I'd prefer a copyOf and non-copyOf versions than one that does both by way of reflection. – rektide Sep 12 '11 at 14:36
3

A type independent variation (UPDATED - thanks to Volley for instantiating T):

@SuppressWarnings("unchecked")
public static <T> T[] join(T[]...arrays) {

    final List<T> output = new ArrayList<T>();

    for(T[] array : arrays) {
        output.addAll(Arrays.asList(array));
    }

    return output.toArray((T[])Array.newInstance(
        arrays[0].getClass().getComponentType(), output.size()));
}
Radiodef
  • 37,180
  • 14
  • 90
  • 125
Damo
  • 11,410
  • 5
  • 57
  • 74
3

I found I had to deal with the case where the arrays can be null...

private double[] concat  (double[]a,double[]b){
    if (a == null) return b;
    if (b == null) return a;
    double[] r = new double[a.length+b.length];
    System.arraycopy(a, 0, r, 0, a.length);
    System.arraycopy(b, 0, r, a.length, b.length);
    return r;

}
private double[] copyRest (double[]a, int start){
    if (a == null) return null;
    if (start > a.length)return null;
    double[]r = new double[a.length-start];
    System.arraycopy(a,start,r,0,a.length-start); 
    return r;
}
user462990
  • 5,472
  • 3
  • 33
  • 35
3
String [] both = new ArrayList<String>(){{addAll(Arrays.asList(first)); addAll(Arrays.asList(second));}}.toArray(new String[0]);
Frimousse
  • 31
  • 4
3
public static String[] toArray(String[]... object){
    List<String> list=new ArrayList<>();
    for (String[] i : object) {
        list.addAll(Arrays.asList(i));
    }
    return list.toArray(new String[list.size()]);
}
3

Every single answer is copying data and creating a new array. This is not strictly necessary and is definitely NOT what you want to do if your arrays are reasonably large. Java creators already knew that array copies are wasteful and that is why they provided us System.arrayCopy() to do those outside Java when we have to.

Instead of copying your data around, consider leaving it in place and draw from it where it lies. Copying data locations just because the programmer would like to organize them is not always sensible.

// I have arrayA and arrayB; would like to treat them as concatenated
// but leave my damn bytes where they are!
Object accessElement ( int index ) {
     if ( index < 0 ) throw new ArrayIndexOutOfBoundsException(...);
     // is reading from the head part?
     if ( index < arrayA.length )
          return arrayA[ index ];
     // is reading from the tail part?
     if ( index < ( arrayA.length + arrayB.length ) )
          return arrayB[ index - arrayA.length ];
     throw new ArrayIndexOutOfBoundsException(...); // index too large
}
Douglas Held
  • 1,452
  • 11
  • 25
3

An easy, but inefficient, way to do this (generics not included):

ArrayList baseArray = new ArrayList(Arrays.asList(array1));
baseArray.addAll(Arrays.asList(array2));
String concatenated[] = (String []) baseArray.toArray(new String[baseArray.size()]);
MetroidFan2002
  • 29,217
  • 16
  • 62
  • 80
3

Using only Javas own API:


String[] join(String[]... arrays) {
  // calculate size of target array
  int size = 0;
  for (String[] array : arrays) {
    size += array.length;
  }

  // create list of appropriate size
  java.util.List list = new java.util.ArrayList(size);

  // add arrays
  for (String[] array : arrays) {
    list.addAll(java.util.Arrays.asList(array));
  }

  // create and return final array
  return list.toArray(new String[size]);
}

Now, this code ist not the most efficient, but it relies only on standard java classes and is easy to understand. It works for any number of String[] (even zero arrays).

2

If you'd like to work with ArrayLists in the solution, you can try this:

public final String [] f(final String [] first, final String [] second) {
    // Assuming non-null for brevity.
    final ArrayList<String> resultList = new ArrayList<String>(Arrays.asList(first));
    resultList.addAll(new ArrayList<String>(Arrays.asList(second)));
    return resultList.toArray(new String [resultList.size()]);
}
Bob Cross
  • 22,116
  • 12
  • 58
  • 95
2

I think the best solution with generics would be:

/* This for non primitive types */
public static <T> T[] concatenate (T[]... elements) {

    T[] C = null;
    for (T[] element: elements) {
        if (element==null) continue;
        if (C==null) C = (T[]) Array.newInstance(element.getClass().getComponentType(), element.length);
        else C = resizeArray(C, C.length+element.length);

        System.arraycopy(element, 0, C, C.length-element.length, element.length);
    }

    return C;
}

/**
 * as far as i know, primitive types do not accept generics 
 * http://stackoverflow.com/questions/2721546/why-dont-java-generics-support-primitive-types
 * for primitive types we could do something like this:
 * */
public static int[] concatenate (int[]... elements){
    int[] C = null;
    for (int[] element: elements) {
        if (element==null) continue;
        if (C==null) C = new int[element.length];
        else C = resizeArray(C, C.length+element.length);

        System.arraycopy(element, 0, C, C.length-element.length, element.length);
    }
    return C;
}

private static <T> T resizeArray (T array, int newSize) {
    int oldSize =
            java.lang.reflect.Array.getLength(array);
    Class elementType =
            array.getClass().getComponentType();
    Object newArray =
            java.lang.reflect.Array.newInstance(
                    elementType, newSize);
    int preserveLength = Math.min(oldSize, newSize);
    if (preserveLength > 0)
        System.arraycopy(array, 0,
                newArray, 0, preserveLength);
    return (T) newArray;
}
spacebiker
  • 3,777
  • 4
  • 30
  • 49
  • This 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 why `Arrays.copyOf` does the same thing, but with a different method name. – Maarten Bodewes Mar 23 '19 at 00:57
  • Not 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. – spacebiker Mar 25 '19 at 19:12
2

Another one based on SilverTab's suggestion, but made to support x number of arguments and not require Java 6. It is also not generic, but I'm sure it could be made generic.

private byte[] concat(byte[]... args)
{
    int fulllength = 0;
    for (byte[] arrItem : args)
    {
        fulllength += arrItem.length;
    }
    byte[] retArray = new byte[fulllength];
    int start = 0;
    for (byte[] arrItem : args)
    {
        System.arraycopy(arrItem, 0, retArray, start, arrItem.length);
        start += arrItem.length;
    }
    return retArray;
}
Tshilidzi Mudau
  • 7,373
  • 6
  • 36
  • 49
Doug
  • 6,446
  • 9
  • 74
  • 107
2
Import java.util.*;

String array1[] = {"bla","bla"};
String array2[] = {"bla","bla"};

ArrayList<String> tempArray = new ArrayList<String>(Arrays.asList(array1));
tempArray.addAll(Arrays.asList(array2));
String array3[] = films.toArray(new String[1]); // size will be overwritten if needed

You could replace String by a Type/Class of your liking

Im sure this can be made shorter and better, but it works and im to lazy to sort it out further...

yankee
  • 38,872
  • 15
  • 103
  • 162
Jeroen
  • 11
  • 1
1
public int[] mergeArrays(int [] a, int [] b) {
    int [] merged = new int[a.length + b.length];
    int i = 0, k = 0, l = a.length;
    int j = a.length > b.length ? a.length : b.length;
    while(i < j) {
        if(k < a.length) {
            merged[k] = a[k];
            k++;
        }
        if((l - a.length) < b.length) {
            merged[l] = b[l - a.length];
            l++;
        }
        i++;
    }
    return merged;
}
George
  • 255
  • 3
  • 18
  • That's very convoluted, hard to understand, undocumented and - with two if statements in the loop - rather inefficient as well. – Maarten Bodewes Mar 23 '19 at 00:51
1

Non Java 8 solution:

public static int[] combineArrays(int[] a, int[] b) {
        int[] c = new int[a.length + b.length];

        for (int i = 0; i < a.length; i++) {
            c[i] = a[i];
        }

        for (int j = 0, k = a.length; j < b.length; j++, k++) {
            c[k] = b[j];
        }

        return c;
    }
BrownRecluse
  • 1,638
  • 1
  • 16
  • 19
1
 /**
     * With Java Streams
     * @param first First Array
     * @param second Second Array
     * @return Merged Array
     */
    String[] mergeArrayOfStrings(String[] first, String[] second) {
        return Stream.concat(Arrays.stream(first), Arrays.stream(second)).toArray(String[]::new);
    }
J.R
  • 2,113
  • 19
  • 21
0

This one works only with int but the idea is generic

public static int[] junta(int[] v, int[] w) {

int[] junta = new int[v.length + w.length];

for (int i = 0; i < v.length; i++) {            
    junta[i] = v[i];
}

for (int j = v.length; j < junta.length; j++) {
    junta[j] = w[j - v.length];
}
Greg Ennis
  • 14,917
  • 2
  • 69
  • 74
Ricardo Vallejo
  • 161
  • 1
  • 4
0
Object[] mixArray(String[] a, String[] b)
String[] s1 = a;
String[] s2 = b;
Object[] result;
List<String> input = new ArrayList<String>();
for (int i = 0; i < s1.length; i++)
{
    input.add(s1[i]);
}
for (int i = 0; i < s2.length; i++)
{
    input.add(s2[i]);
}
result = input.toArray();
return result;
Tshilidzi Mudau
  • 7,373
  • 6
  • 36
  • 49
obwan02
  • 113
  • 10
0

Yet another answer for algorithm lovers:

public static String[] mergeArrays(String[] array1, String[] array2) {
    int totalSize = array1.length + array2.length; // Get total size
    String[] merged = new String[totalSize]; // Create new array
    // Loop over the total size
    for (int i = 0; i < totalSize; i++) {
        if (i < array1.length) // If the current position is less than the length of the first array, take value from first array
            merged[i] = array1[i]; // Position in first array is the current position

        else // If current position is equal or greater than the first array, take value from second array.
            merged[i] = array2[i - array1.length]; // Position in second array is current position minus length of first array.
    }

    return merged;

Usage:

String[] array1str = new String[]{"a", "b", "c", "d"}; 
String[] array2str = new String[]{"e", "f", "g", "h", "i"};
String[] listTotalstr = mergeArrays(array1str, array2str);
System.out.println(Arrays.toString(listTotalstr));

Result:

[a, b, c, d, e, f, g, h, i]
c-chavez
  • 7,237
  • 5
  • 35
  • 49
  • An if statement per copy is not a brilliant idea as it will have a hefty performance hit. – Maarten Bodewes Mar 23 '19 at 00:34
  • @MaartenBodewes it's always nice to learn new approaches focused on performance. Any suggestions to improve this? – c-chavez Mar 23 '19 at 11:58
  • Well, yes, `arrayCopy` but I guess that's mentioned in quite a few other examples. Same for two or more `for` loops; it is possible to bring the branching (the if statements) out of the loop. – Maarten Bodewes Mar 23 '19 at 15:41
0

You can try this method which concatenates multiple arrays:

public static <T> T[] concatMultipleArrays(T[]... arrays)
{
   int length = 0;
   for (T[] array : arrays)
   {
      length += array.length;
   }
   T[] result = (T[]) Array.newInstance(arrays.getClass().getComponentType(), length) ;

   length = 0;
   for (int i = 0; i < arrays.length; i++)
   {
      System.arraycopy(arrays[i], 0, result, length, arrays[i].length);
      length += arrays[i].length;
   }

   return result;
}
Hakim
  • 434
  • 7
  • 21
0

In Java 8

public String[] concat(String[] arr1, String[] arr2){
    Stream<String> stream1 = Stream.of(arr1);
    Stream<String> stream2 = Stream.of(arr2);
    Stream<String> stream = Stream.concat(stream1, stream2);
    return Arrays.toString(stream.toArray(String[]::new));
}
Neuron
  • 5,141
  • 5
  • 38
  • 59
Basil Battikhi
  • 2,638
  • 1
  • 18
  • 34
  • This is the same as a previous answer 10 Feb 16. – rghome Apr 16 '18 at 12:29
  • @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 Mar 23 '19 at 15:44
0
Object[] obj = {"hi","there"};
Object[] obj2 ={"im","fine","what abt u"};
Object[] obj3 = new Object[obj.length+obj2.length];

for(int i =0;i<obj3.length;i++)
    obj3[i] = (i<obj.length)?obj[i]:obj2[i-obj.length];
Adham
  • 490
  • 4
  • 12
0

concatenates a series of arrays compact, fast and type-safe with lambda

@SafeVarargs
public static <T> T[] concat( T[]... arrays ) {
  return( Stream.of( arrays ).reduce( ( arr1, arr2 ) -> {
      T[] rslt = Arrays.copyOf( arr1, arr1.length + arr2.length );
      System.arraycopy( arr2, 0, rslt, arr1.length, arr2.length );
      return( rslt );
    } ).orElse( null ) );
};

returns null when called without argument

eg. example with 3 arrays:

String[] a = new String[] { "a", "b", "c", "d" };
String[] b = new String[] { "e", "f", "g", "h" };
String[] c = new String[] { "i", "j", "k", "l" };

concat( a, b, c );  // [a, b, c, d, e, f, g, h, i, j, k, l]


"…probably the only generic and type-safe way" – adapted:

Number[] array1 = { 1, 2, 3 };
Number[] array2 = { 4.0, 5.0, 6.0 };
Number[] array = concat( array1, array2 );  // [1, 2, 3, 4.0, 5.0, 6.0]
Kaplan
  • 2,572
  • 13
  • 14
0

Just wanted to add, you can use System.arraycopy too:

import static java.lang.System.out;
import static java.lang.System.arraycopy;
import java.lang.reflect.Array;
class Playground {
    @SuppressWarnings("unchecked")
    public static <T>T[] combineArrays(T[] a1, T[] a2) {
        T[] result = (T[]) Array.newInstance(a1.getClass().getComponentType(), a1.length+a2.length);
        arraycopy(a1,0,result,0,a1.length);
        arraycopy(a2,0,result,a1.length,a2.length);
        return result;
    }
    public static void main(String[ ] args) {
        String monthsString = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
        String[] months = monthsString.split("(?<=\\G.{3})");
        String daysString = "SUNMONTUEWEDTHUFRISAT";
        String[] days = daysString.split("(?<=\\G.{3})");
        for (String m : months) {
            out.println(m);
        }
        out.println("===");
         for (String d : days) {
            out.println(d);
        }
        out.println("===");
        String[] results = combineArrays(months, days);
        for (String r : results) {
            out.println(r);
        }
        out.println("===");
    }
}
JGFMK
  • 8,425
  • 4
  • 58
  • 92
0

The easiest way i could find is as following :


List allFiltersList = Arrays.asList(regularFilters);
allFiltersList.addAll(Arrays.asList(preFiltersArray));
Filter[] mergedFilterArray = (Filter[]) allFiltersList.toArray();

0

I use next method to concatenate any number of arrays of the same type using java 8:

public static <G> G[] concatenate(IntFunction<G[]> generator, G[] ... arrays) {
    int len = arrays.length;
    if (len == 0) {
        return generator.apply(0);
    } else if (len == 1) {
        return arrays[0];
    }
    int pos = 0;
    Stream<G> result = Stream.concat(Arrays.stream(arrays[pos]), Arrays.stream(arrays[++pos]));
    while (pos < len - 1) {
        result = Stream.concat(result, Arrays.stream(arrays[++pos]));
    }
    return result.toArray(generator);
}

usage:

 concatenate(String[]::new, new String[]{"one"}, new String[]{"two"}, new String[]{"three"}) 

or

 concatenate(Integer[]::new, new Integer[]{1}, new Integer[]{2}, new Integer[]{3})
0

I just discovered this question, sorry very late, and saw a lot of answers that were too far away, using certain libraries, using the feature of converting data from an array to a stream and back to an array and so on. But, we can just use a simple loop and the problem is done

public String[] concat(String[] firstArr,String[] secondArr){
        //if both is empty just return
        if(firstArr.length==0 && secondArr.length==0)return new String[0];

        String[] res = new String[firstArr.length+secondArr.length];
        int idxFromFirst=0;

        //loop over firstArr, idxFromFirst will be used as starting offset for secondArr
        for(int i=0;i<firstArr.length;i++){
            res[i] = firstArr[i];
            idxFromFirst++;
        }

        //loop over secondArr, with starting offset idxFromFirst (the offset track from first array)
        for(int i=0;i<secondArr.length;i++){
            res[idxFromFirst+i]=secondArr[i];
        }

        return res;
    }

Thats it all, right? he didnt say he care about the order or anything. This should be the easiest way of it.

rizesky
  • 424
  • 6
  • 13
0

You can try this

 public static Object[] addTwoArray(Object[] objArr1, Object[] objArr2){
    int arr1Length = objArr1!=null && objArr1.length>0?objArr1.length:0;
    int arr2Length = objArr2!=null && objArr2.length>0?objArr2.length:0;
    Object[] resutlentArray = new Object[arr1Length+arr2Length]; 
    for(int i=0,j=0;i<resutlentArray.length;i++){
        if(i+1<=arr1Length){
            resutlentArray[i]=objArr1[i];
        }else{
            resutlentArray[i]=objArr2[j];
            j++;
        }
    }

    return resutlentArray;
}

U can type cast your array !!!

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Sushim
  • 11
  • 1
0

I have a simple method. You don't want to waste your time to research complex java functions or libraries. But the return type should be String.

String[] f(String[] first, String[] second) {

    // Variable declaration part
    int len1 = first.length;
    int len2 = second.length;
    int lenNew = len1 + len2;
    String[] both = new String[len1+len2];

    // For loop to fill the array "both"
    for (int i=0 ; i<lenNew ; i++){
        if (i<len1) {
            both[i] = first[i];
        } else {
            both[i] = second[i-len1];
        }
    }

    return both;

}

So simple...

Lakshitha Kanchana
  • 844
  • 2
  • 12
  • 32
0

Using Java Collections

Well, Java doesn't provide a helper method to concatenate arrays. However, since Java 5, the Collections utility class has introduced an addAll(Collection<? super T> c, T… elements) method.

We can create a List object, then call this method twice to add the two arrays to the list. Finally, we convert the resulting List back to an array:

static <T> T[] concatWithCollection(T[] array1, T[] array2) {
    List<T> resultList = new ArrayList<>(array1.length + array2.length);
    Collections.addAll(resultList, array1);
    Collections.addAll(resultList, array2);

    @SuppressWarnings("unchecked")
    //the type cast is safe as the array1 has the type T[]
    T[] resultArray = (T[]) Array.newInstance(array1.getClass().getComponentType(), 0);
    return resultList.toArray(resultArray);
}

Test

@Test
public void givenTwoStringArrays_whenConcatWithList_thenGetExpectedResult() {
    String[] result = ArrayConcatUtil.concatWithCollection(strArray1, strArray2);
    assertThat(result).isEqualTo(expectedStringArray);
}

Rajesh Patel
  • 170
  • 1
  • 1
  • 13
0

I tested below code and worked ok

Also I'm using library: org.apache.commons.lang.ArrayUtils

public void testConcatArrayString(){
    String[] a = null;
    String[] b = null;
    String[] c = null;
    a = new String[] {"1","2","3","4","5"};
    b = new String[] {"A","B","C","D","E"};

    c = (String[]) ArrayUtils.addAll(a, b);
    if(c!=null){
        for(int i=0; i<c.length; i++){
            System.out.println("c[" + (i+1) + "] = " + c[i]);
        }
    }
}

Regards

0

I see many generic answers with signatures such as public static T[] concat(T[] a, T[] b) {} but these only work on Object arrays, not on primitive arrays, as far as I can work out. The code below works both on Object and primitive arrays, making it more generic...

public static <T> T concat(T a, T b) {
        //Handles both arrays of Objects and primitives! E.g., int[] out = concat(new int[]{6,7,8}, new int[]{9,10});
        //You get a compile error if argument(s) not same type as output. (int[] in example above)
        //You get a runtime error if output type is not an array, i.e., when you do something like: int out = concat(6,7);
        if (a == null && b == null) return null;
        if (a == null) return b;
        if (b == null) return a;
        final int aLen = Array.getLength(a);
        final int bLen = Array.getLength(b);
        if (aLen == 0) return b;
        if (bLen == 0) return a;
        //From here on we really need to concatenate!

        Class componentType = a.getClass().getComponentType();
        final T result = (T)Array.newInstance(componentType, aLen + bLen);
        System.arraycopy(a, 0, result, 0, aLen);
        System.arraycopy(b, 0, result, aLen, bLen);
        return result;
    }

    public static void main(String[] args) {
        String[] out1 = concat(new String[]{"aap", "monkey"}, new String[]{"rat"});
        int[] out2 = concat(new int[]{6,7,8}, new int[]{9,10});
    }
mkemper
  • 57
  • 6
-1

Look at this elegant solution (if you need other type than char, change it):

private static void concatArrays(char[] destination, char[]... sources) {
    int currPos = 0;
    for (char[] source : sources) {
        int length = source.length;
        System.arraycopy(source, 0, destination, currPos, length);
        currPos += length;
    }
}

You can concatenate a every count of arrays.

filosofem
  • 11
  • 1
  • Welcome 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. – Leigh Apr 07 '12 at 19:59
  • 1
    This 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. – Adriaan Koster Apr 12 '15 at 22:01
-1

Should do the trick. This is assuming String[] first and String[] second

List<String> myList = new ArrayList<String>(Arrays.asList(first));
myList.addAll(new ArrayList<String>(Arrays.asList(second)));
String[] both = myList.toArray(new String[myList.size()]);
SuperCamp
  • 36
  • 2
  • `myList.addAll(new ArrayList(Arrays.asList(second)));` can be simplified to `myList.addAll(Arrays.asList(second))` – slartidan May 24 '17 at 14:07
-1
    void f(String[] first, String[] second) {
    String[] both = new String[first.length+second.length];
    for(int i=0;i<first.length;i++)
        both[i] = first[i];
    for(int i=0;i<second.length;i++)
        both[first.length + i] = second[i];
}

This one works without knowledge of any other classes/libraries etc. It works for any data type. Just replace String with anything like int,double or char. It works quite efficiently.

Yashovardhan99
  • 887
  • 11
  • 26
-1

In Haskell you can do something like that [a, b, c] ++ [d, e] to get [a, b, c, d, e]. These are Haskell lists concatenated but that'd very nice to see a similar operator in Java for arrays. Don't you think so ? That's elegant, simple, generic and it's not that difficult to implement.

If you want to, I suggest you to have a look at Alexander Hristov's work in his Hacking the OpenJDK compiler. He explains how to modify javac source to create a new operator. His example consists in defining a '**' operator where i ** j = Math.pow(i, j). One could take that example to implement an operator that concatenates two arrays of same type.

Once you do that, you are bound to your customized javac to compile your code but the generated bytecode will be understood by any JVM.

Of course, you can implement your own array concatenatation method at your source level, there are many examples on how to do it in the other answers !

There are so many useful operators that could be added, this one would be one of them.

Jerome
  • 4,472
  • 4
  • 18
  • 18
-2

Here is what worked for me:

String[] data=null;
String[] data2=null;
ArrayList<String> data1 = new ArrayList<String>();
for(int i=0; i<2;i++) {
   data2 = input.readLine().split(",");
   data1.addAll(Arrays.asList(data2));
   data= data1.toArray(new String[data1.size()]);
   }
Areeha
  • 823
  • 7
  • 11