在Java中合并两个数组?

Join two arrays in Java?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
How to concatenate two arrays in Java?

我有两个东西

1
2
3
4
5
6
7
HealthMessage[] healthMessages1;
HealthMessage[] healthMessages2;

HealthMessage[] healthMessagesAll;

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

我应该如何连接这两个对象,以便只返回一个:

1
return healthMessagesAll;

推荐的方法是什么?


使用Apache Commons Collecion API是一种很好的方法:

1
healthMessagesAll = ArrayUtils.addAll(healthMessages1,healthMessages2);


我将分配一个总长度为healthMessages1healthMessages2的数组,并使用System.arraycopy或两个for循环来复制它们的内容。这是一个带有System.arraycopy的样本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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);
        }            
     }        
}


这样写起来更直观,不必处理数组索引:

1
2
3
4
5
Collection<HealthMessage> collection = new ArrayList<HealthMessage>();
collection.addAll(Arrays.asList(healthMessages1));
collection.addAll(Arrays.asList(healthMessages2));

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

…但不要问我它的性能与System.arraycopy相比。


我会和System.arraycopy一起去

1
2
3
4
5
6
7
8
9
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;
}

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
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));

  }
}


沿着这条路怎么办:

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

(需要一点基因改造…:)


数组是固定长度的,所以您有多种选择。以下是一些:

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

1
2
3
4
5
6
7
8
9
10
11
12
13
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)使用array类提供的方法。您可以将数组转换为列表,或者批量复制元素。看看它提供的功能,然后选择适合您的功能。

更新

查看您对重复项的评论。您可能希望将所有内容都放在一个保证唯一性的Set中。如果将同一元素添加两次,则不会再次添加该元素。然后,如果显式地需要一个具有自己的toArray()方法的数组,则可以将该集合转换回数组。

正如其他受访者所建议的,system.arraycopy()也可以帮助您复制元素的内容,因此它是上面我的替代(a)的较短版本。