在Java中如何合并两个数组?

19

可能与以下问题重复:
如何在Java中连接两个数组?

我有两个对象

HealthMessage[] healthMessages1;
HealthMessage[] healthMessages2;

HealthMessage[] healthMessagesAll;

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

我应该如何将这两个对象合并,以便只返回一个:

return healthMessagesAll;

什么是推荐的方式?


尝试使用此链接:https://dev59.com/q3I-5IYBdhLWcg3wMFMf - Subhrajyoti Majumder
你想如何处理重复项?比如说Array1有3个重复项,不考虑Array2,那么这3个重复项应该在resultantArray中全部出现吗? - Jayy
好问题Kaipa,没有考虑到重复。 - Danijel
1
在Java 8中终于可以用一行代码实现,具体描述可参考https://dev59.com/Q3VD5IYBdhLWcg3wHn2d#23188881。 - Marek Gregor
7个回答

38

使用Apache Commons Collections API是一种不错的方式:

healthMessagesAll = ArrayUtils.addAll(healthMessages1,healthMessages2);

3
如果您能使用 Apache Commons,就不需要重新发明轮子了,这样会更加优雅。+1 - Matthias Meid
最佳答案,是的。 - ennth

21

我会分配一个长度为healthMessages1healthMessages2之和的数组,然后使用System.arraycopy或两个for循环将它们的内容复制过去。以下是使用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);
        }            
     }         
}

14

这种写法更加直观且不需要处理数组索引:

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

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

...... 但不要问我与System.arraycopy相比的性能如何。


1
+1 给一个漂亮、干净、简单的解决方案。 - sunil

4
我会选择使用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;
}

0

数组长度是固定的,因此您有多种选择。以下是其中的两个:

a)创建一个新数组,大小与其他数组相同,并手动复制所有元素。

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++;
}
第二步:使用Arrays类提供的方法。您可以将数组转换为列表,或者批量复制元素。查看它提供的函数并选择适合您的函数。

更新

根据您关于重复项的评论。您可能希望将所有内容放入Set中,以确保唯一性。如果您两次添加相同的元素,则不会第二次添加。 然后,如果您明确需要具有自己的toArray()方法的数组,则可以将Set转换回数组。

如其他回答者建议的那样,System.arraycopy()也可以帮助您复制元素的内容,因此它是我上面替代方案(a)的简短版本。


0

对于最复杂但最节省内存的解决方案,您可以将它们封装在一个对象中。该对象提供了一个跨所有项目的Iterator<T>和一个copyTo方法来复制到新数组。它可以很容易地增强以提供getter和setter。

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));

  }
}

不错,但别忘了单元测试;-) - Kai

-1

关于这个问题,我们可以这样考虑:

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

(需要一些泛化... :)


Arrays.asList(T... a) 返回一个固定大小的列表。你会在第二行遇到异常。 - Fabrice TIERCELIN

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接