19

Possible Duplicate:
How to concatenate two arrays in Java?

I have two objects

HealthMessage[] healthMessages1;
HealthMessage[] healthMessages2;

HealthMessage[] healthMessagesAll;

healthMessages1 = x.getHealth( );   
healthMessages2 = y.getHealth( );

How should I join the two objects, so I can return only one:

return healthMessagesAll;

What's the recommended way?

Community
  • 1
  • 1
Danijel
  • 8,198
  • 18
  • 69
  • 133
  • try [this](http://stackoverflow.com/questions/1978933/a-quick-and-easy-way-to-join-array-elements-with-a-separator-the-oposite-of-spl) – Subhrajyoti Majumder Nov 27 '12 at 11:47
  • How do you want to handle the duplicates? Say Array1 has 3 duplicates without considering Array2, then all 3 duplicates should be available in resultantArray? – Jayy Nov 27 '12 at 11:48
  • Good question Kaipa, didn't think about duplicates. – Danijel Nov 27 '12 at 11:50
  • 1
    Finally in Java 8 it's possible with one line, described in http://stackoverflow.com/a/23188881/466677 – Marek Gregor Jan 12 '15 at 09:30

7 Answers7

38

Using Apache Commons Collections API is a good way:

healthMessagesAll = ArrayUtils.addAll(healthMessages1,healthMessages2);
Chexpir
  • 1,876
  • 18
  • 33
21

I'd allocate an array with the total length of healthMessages1 and healthMessages2 and use System.arraycopy or two for loops to copy their contents. Here is a sample with System.arraycopy:

public class HelloWorld {

     public static void main(String []args) {

        int[] a = new int[] { 1, 2, 3};
        int[] b = new int[] { 3, 4, 5};
        int[] r = new int[a.length + b.length];
        System.arraycopy(a, 0, r, 0, a.length);
        System.arraycopy(b, 0, r, a.length, b.length);

        // prints 1, 2, 3, 4, 5 on sep. lines
        for(int x : r) {
            System.out.println(x);
        }            
     }         
}
Matthias Meid
  • 12,455
  • 7
  • 45
  • 79
14

This is more intuitive to write and you don't have to deal with array indexes:

Collection<HealthMessage> collection = new ArrayList<HealthMessage>();
collection.addAll(Arrays.asList(healthMessages1));
collection.addAll(Arrays.asList(healthMessages2));

HealthMessage[] healthMessagesAll = collection.toArray(new HealthMessage[] {});

.. but don't ask me about it's performance in contrast to System.arraycopy.

Kai
  • 38,985
  • 14
  • 88
  • 103
4

I would go with System.arraycopy

private static HealthMessage[] join(HealthMessage[] healthMessages1, HealthMessage[] healthMessages2)
{
    HealthMessage[] healthMessagesAll = new HealthMessage[healthMessages1.length + healthMessages2.length];

    System.arraycopy(healthMessages1, 0, healthMessagesAll, 0, healthMessages1.length);
    System.arraycopy(healthMessages2, 0, healthMessagesAll, healthMessages1.length, healthMessages2.length);

    return healthMessagesAll;
}
sunil
  • 6,444
  • 1
  • 32
  • 44
0

Arrays are fixed length, so you have various alternatives. Here are a couple:

a) Create a new array with the size of the others and copy all the elements manually.

healthMessagesAll = new HealthMessage[healthMessages1.length + healthMessages2.length];
int i = 0;
for (HealthMessage msg : healthMessases1)
{
   healthMessagesAll[i] = msg;
   i++;
}

for (HealthMessage msg : healthMessages2)
{
   healthMessagesAll[i] = msg;
   i++;
}

b) Use the methods provided by the Arrays class. You can convert the array to a List, or copy elements around in bulk. Have a look at the functions it provides and choose the one that suits you.

UPDATE

Seeing your comment about duplicates. You might want to put everything in a Set which guarantees uniqueness. If you add the same element twice, it won't be added the second time. You can then convert the Set back to an array if you explicitly require an array with its own toArray() method.

As suggested by other respondents, System.arraycopy() helps you copy the contents of the elements too, so its a shorter version of my alternative (a) above.

jbx
  • 21,365
  • 18
  • 90
  • 144
0

And for the most complex but least memory-hungry solution you can wrap them in an object. This one provides an Iterator<T> across all of the items and a copyTo method to copy to a new array. It could be easily enhanced to provide getters and setters.

public class JoinedArray<T> implements Iterable<T> {
  final List<T[]> joined;

  // Pass all arrays to be joined as constructor parameters.
  public JoinedArray(T[]... arrays) {
    joined = Arrays.asList(arrays);
  }

  // Iterate across all entries in all arrays (in sequence).
  public Iterator<T> iterator() {
    return new JoinedIterator<T>(joined);
  }

  private class JoinedIterator<T> implements Iterator<T> {
    // The iterator across the arrays.
    Iterator<T[]> i;
    // The array I am working on. Equivalent to i.next without the hassle.
    T[] a;
    // Where we are in it.
    int ai;
    // The next T to return.
    T next = null;

    private JoinedIterator(List<T[]> joined) {
      i = joined.iterator();
      a = nextArray();
    }

    private T[] nextArray () {
      ai = 0;
      return i.hasNext() ? i.next() : null;
    }

    public boolean hasNext() {
      if (next == null) {
        // a goes to null at the end of i.
        if (a != null) {
          // End of a?
          if (ai >= a.length) {
            // Yes! Next i.
            a = nextArray();
          }
          if (a != null) {
            next = a[ai++];
          }
        }
      }
      return next != null;
    }

    public T next() {
      T n = null;
      if (hasNext()) {
        // Give it to them.
        n = next;
        next = null;
      } else {
        // Not there!!
        throw new NoSuchElementException();
      }
      return n;
    }

    public void remove() {
      throw new UnsupportedOperationException("Not supported.");
    }
  }

  public int copyTo(T[] to, int offset, int length) {
    int copied = 0;
    // Walk each of my arrays.
    for (T[] a : joined) {
      // All done if nothing left to copy.
      if (length <= 0) {
        break;
      }
      if (offset < a.length) {
        // Copy up to the end or to the limit, whichever is the first.
        int n = Math.min(a.length - offset, length);
        System.arraycopy(a, offset, to, copied, n);
        offset = 0;
        copied += n;
        length -= n;
      } else {
        // Skip this array completely.
        offset -= a.length;
      }
    }
    return copied;
  }

  public int copyTo(T[] to, int offset) {
    return copyTo(to, offset, to.length);
  }

  public int copyTo(T[] to) {
    return copyTo(to, 0);
  }

  @Override
  public String toString() {
    StringBuilder s = new StringBuilder();
    Separator comma = new Separator(",");
    for (T[] a : joined) {
      s.append(comma.sep()).append(Arrays.toString(a));
    }
    return s.toString();
  }

  public static void main(String[] args) {
    JoinedArray<String> a = new JoinedArray<String>(
            new String[]{
              "One"
            },
            new String[]{
              "Two",
              "Three",
              "Four",
              "Five"
            },
            new String[]{
              "Six",
              "Seven",
              "Eight",
              "Nine"
            });
    for (String s : a) {
      System.out.println(s);
    }
    String[] four = new String[4];
    int copied = a.copyTo(four, 3, 4);
    System.out.println("Copied " + copied + " = " + Arrays.toString(four));

  }
}
OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
-1

what about something along this way:

    List<String> l1 = Arrays.asList(healthMessages1);
    l1.addAll(Arrays.asList(healthMessages2));
    HealthMessage[] result = l1.toArray();

(needs a bit of generification... :)

alvi
  • 2,622
  • 1
  • 22
  • 34