Ccna final exam - java, php, javascript, ios, cshap all in one. This is a collaboratively edited question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.
Here's a method that will concatenate 2 arrays of type T (replace the T in the code with your classname in question, this is just pseudocode not generics).
T[] concat(T[] A, T[] B) { T[] C= new T[A.length+B.length]; System.arraycopy(A, 0, C, 0, A.length); System.arraycopy(B, 0, C, A.length, B.length);
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.
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[] 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; }
(In either case, array re-usage behaviour shall be clearly JavaDoced!)
// 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).
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.
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; }
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"};
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; }
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...
public static T[] concat(T[]... arrays) { ArrayList al = new ArrayList(); 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.
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.
I found a one-line solution from the good old Apache Commons Lang library. ArrayUtils.addAll(T[], T...). Code:
ReplyDeleteString[] both = ArrayUtils.addAll(first, second);
Here's a method that will concatenate 2 arrays of type T (replace the T in the code with your classname in question, this is just pseudocode not generics).
ReplyDeleteT[] concat(T[] A, T[] B) {
T[] C= new T[A.length+B.length];
System.arraycopy(A, 0, C, 0, A.length);
System.arraycopy(B, 0, C, A.length, B.length);
return C;
}
(source: Sun Forum )
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()
ReplyDeleteBoth 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;
}
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):
ReplyDeleteprivate static <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;
}
(In either case, array re-usage behaviour shall be clearly JavaDoced!)
The Functional Java library has an array wrapper class that equips arrays with handy methods like concatenation.
ReplyDeleteimport 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();
Here's an adaptation of silvertab's solution, with generics retrofitted:
ReplyDeletestatic <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!
Using the Java API:
ReplyDeleteString[] 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()]);
}
Or with the loved Guava:
ReplyDeleteString[] both = ObjectArrays.concat(first, second, String.class);
Using only Javas own API:
ReplyDeleteString[] 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).
Here a possible implementation in working code of the pseudo code solution written by silvertab.
ReplyDeleteThanks 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]);
}
}
This works, but you need to insert your own error checking.
ReplyDeletepublic 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.
An easy, but inefficient, way to do this (generics not included):
ReplyDeleteArrayList baseArray = new ArrayList(Arrays.asList(array1));
baseArray.addAll(Arrays.asList(array2));
String concatenated[] = (String []) baseArray.toArray(new String[baseArray.size()]);
Object[] obj = {"hi","there"};
ReplyDeleteObject[] 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];
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.
ReplyDeletepublic 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;
}
If you'd like to work with ArrayLists in the solution, you can try this:
ReplyDeletepublic 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()]);
}
I tested below code and worked ok
ReplyDeleteAlso 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
A simple variation allowing the joining of more than one array:
ReplyDeletepublic 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()]);
}
A type independent variation (UPDATED - thanks to Volley for instantiating T):
ReplyDelete@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()));
}
/**
ReplyDelete* Concatenates two arrays.
*
* @param array1 - first array
* @param array2 - second array
* @param <T> - object class
* @return array contatenation
*/
public static <T> T[] concatenate(T[] array1, T... array2) {
List<T> result = new ArrayList<T>();
result.addAll(Arrays.asList(array1));
result.addAll(Arrays.asList(array2));
return result.toArray(array1);
}
public String[] concat(String[]... arrays)
ReplyDelete{
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;
}
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.
ReplyDeleteprivate 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;
}
The easiest way i could find is as following :
ReplyDeleteList allFiltersList = Arrays.asList(regularFilters);
allFiltersList.addAll(Arrays.asList(preFiltersArray));
Filter[] mergedFilterArray = (Filter[]) allFiltersList.toArray();
This is a converted function for a String array:
ReplyDeletepublic 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;
}
Import java.util.*;
ReplyDeleteString 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...
You can try this
ReplyDeletepublic 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 !!!!!!
Hope it will help u
Cheer :)
How about simply
ReplyDeletepublic static class Array {
public static T[] concat(T[]... arrays) {
ArrayList al = new ArrayList();
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.
A solution 100% old java and without System.arraycopy (not available in GWT client for example):
ReplyDeletestatic String[] concat(String[]... arrays) {
int lengh = 0;
for (String[] array : arrays) {
lengh += array.length;
}
String[] result = new String[lengh];
int pos = 0;
for (String[] array : arrays) {
for (String element : array) {
result[pos] = element;
pos++;
}
}
return result;
}
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.
ReplyDeleteIf 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.
Look at this elegant solution (if you need other type than char, change it):
ReplyDeleteprivate 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.
String[] both = Arrays.asList(first).addAll(Arrays.asList(second)).toArray();
ReplyDelete