Como concatenar duas matrizes em Java?


1366

Eu preciso concatenar duas Stringmatrizes em Java.

void f(String[] first, String[] second) {
    String[] both = ???
}

Qual é a maneira mais fácil de fazer isso?


3
Bytes.concat de Guava
Ben Página

1
Eu vejo um monte de respostas aqui, mas a questão é assim redigido ( 'caminho mais fácil'?) Que não permitem indicar a melhor resposta ...
Artur Opalinski

2
Dezenas de respostas aqui estão copiando os dados em uma nova matriz, porque foi o que foi solicitado - mas copiar dados quando não estritamente necessário é uma coisa ruim a se fazer, especialmente em Java. Em vez disso, acompanhe os índices e use as duas matrizes como se fossem unidas. Eu adicionei uma solução que ilustra a técnica.
Douglas Held

12
O fato de uma pergunta como essa ter atualmente 50 respostas diferentes me faz pensar por que o Java nunca teve uma array1 + array2concatenação simples .
JollyJoker #

2
Você pode fazê-lo perfeitamente bem e com muita eficiência em duas linhas de Java padrão (veja minha resposta); portanto, não há muito a ganhar com um único método para fazê-lo. Todas essas soluções estranhas e maravilhosas são uma perda de tempo.
Rgome

Respostas:


1093

Encontrei uma solução de uma linha na boa e antiga biblioteca Apache Commons Lang.
ArrayUtils.addAll(T[], T...)

Código:

String[] both = ArrayUtils.addAll(first, second);

175
Como é "trapacear" se responde à pergunta? Certamente, ter uma dependência extra provavelmente é um exagero para essa situação específica, mas nenhum dano é causado ao afirmar que ela existe, especialmente porque há tantos bits excelentes de funcionalidade no Apache Commons.
1026 Rob

33
Eu concordo, isso realmente não está respondendo à pergunta. Bibliotecas de alto nível podem ser ótimas, mas se você quiser aprender uma maneira eficiente de fazê-lo, consulte o código que o método da biblioteca está usando. Além disso, em muitas situações, você não pode simplesmente passar por outra biblioteca do produto em tempo real.
1811 AdamC

76
Eu acho que essa é uma boa resposta. As soluções POJO também foram fornecidas, mas se o OP já estiver usando o Apache Commons em seu programa (totalmente possível, considerando sua popularidade), ele ainda poderá não conhecer essa solução. Então ele não estaria "adicionando uma dependência para esse método", mas estaria aproveitando melhor uma biblioteca existente.
Adam

14
Se você está sempre preocupado em não adicionar uma biblioteca para um único método, nenhuma nova biblioteca será adicionada. Dado os excelentes utilitários presentes no Apache Commons, eu recomendo adicioná-lo quando surgir o primeiro caso de uso.
Hindol

6
o uso do apache commons nunca deve ser chamado de "trapaça". Questiono a sanidade dos desenvolvedores que consideram uma dependência desnecessária.
21136 Jerry Cook

768

Aqui está um método simples que concatenará duas matrizes e retornará o resultado:

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

Observe que ele não funcionará com tipos de dados primitivos, apenas com tipos de objetos.

A seguinte versão um pouco mais complicada funciona com matrizes de objeto e primitivas. Faz isso usando em Tvez de T[]como o tipo de argumento.

Também possibilita concatenar matrizes de dois tipos diferentes, escolhendo o tipo mais geral como o tipo de componente do resultado.

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

Aqui está um exemplo:

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

1
Eu gosto dessa sugestão, pois é menos dependente das versões mais recentes do Java. Nos meus projetos, muitas vezes estou preso ao uso de versões mais antigas dos perfis Java ou CLDC, onde algumas das facilidades como as mencionadas pela Antti não estão disponíveis.
kvn

4
A linha a seguir vai quebrar a parte genérica: concatenate (new String [] { "1"}, new Object [] {new Object ()})
dragon66

seria bom não precisar usar a anotação @SuppressWarnings - postarei uma solução para isso abaixo.
22718 beaudet

+1 para Array.newInstance(a.getClass().getComponentType(), aLen + bLen);. Surpreendentemente, nunca vi isso antes. @ Beaudet Acho que a anotação está bem aqui, considerando por que está sendo suprimida.
Blake

1
ha, me chame um purista, mas eu prefiro código limpo que não requer supressão de avisos, a fim de remover os avisos
beaudet

475

É possível escrever uma versão totalmente genérica que pode até ser estendida para concatenar qualquer número de matrizes. Essas versões requerem Java 6, pois usamArrays.copyOf()

Ambas as versões evitam a criação de Listobjetos intermediários e são usadas System.arraycopy()para garantir que a cópia de matrizes grandes seja o mais rápida possível.

Para duas matrizes, fica assim:

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

E para um número arbitrário de matrizes (> = 1), fica assim:

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

10
@djBO: para matrizes de tipo primitivo, você precisará sobrecarregar cada tipo: basta copiar o código e substituí-lo Tpor byte(e perder o <T>).
Joachim Sauer

você pode me dizer como usar o tipo de operador <T> na minha classe?
31411 Johnydep

6
Eu adicionaria isso ao começo, só para ficar na defensiva. if (primeiro == nulo) {if (segundo == nulo) {retorna nulo; } retornar segundo; } if (segundo == nulo) {retorna primeiro; }
maratona

4
@djBo: what about:ByteBuffer buffer = ByteBuffer.allocate(array1.length + array2.length); buffer.put(array1); buffer.put(array2); return buffer.array();
Sam Goldberg

18
Existe um bug nessa abordagem que se torna aparente se você invocar essas funções com matrizes de diferentes tipos de componentes, por exemplo concat(ai, ad), onde aiestá Integer[]e adestá Double[]. (Nesse caso, o parâmetro type <T>é resolvido <? extends Number>pelo compilador.) A matriz criada por Arrays.copyOfterá o tipo de componente da primeira matriz, ou seja Integer, neste exemplo. Quando a função está prestes a copiar a segunda matriz, um ArrayStoreExceptionserá lançado. A solução é ter um Class<T> typeparâmetro adicional .
T-Bull

457

Usando Streamno Java 8:

String[] both = Stream.concat(Arrays.stream(a), Arrays.stream(b))
                      .toArray(String[]::new);

Ou assim, usando flatMap:

String[] both = Stream.of(a, b).flatMap(Stream::of)
                      .toArray(String[]::new);

Para fazer isso para um tipo genérico, você precisa usar a reflexão:

@SuppressWarnings("unchecked")
T[] both = Stream.concat(Arrays.stream(a), Arrays.stream(b)).toArray(
    size -> (T[]) Array.newInstance(a.getClass().getComponentType(), size));

28
Quão eficiente é isso?
Supuhstar

8
Vale a pena ler: jaxenter.com/… tl; dr - streams pode ter bom desempenho ou não, depende do que você está fazendo com eles e das restrições do problema (essa nem sempre é a resposta?)
Trevor Brown

6
Além disso, se a ou b são matrizes de tipos primitivos, seus fluxos precisarão ser de .boxed()modo que sejam do tipo Streame não, por exemplo, IntStreamque não possam ser passados ​​como parâmetro para Stream.concat.
Will Hardwick-Smith

17
@Will Hardwick-Smith: não, você só tem que escolher a classe fluxo de direita, por exemplo, se ae bsão int[], usoint[] both = IntStream.concat(Arrays.stream(a), Arrays.stream(b)).toArray();
Holger

3
@ Supuhstar: Provavelmente não é tão rápido quanto System.arrayCopy. Mas também não é particularmente lento. Você provavelmente tem que fazer isso uma muito muitas vezes com enormes matrizes em realmente contextos sensíveis de desempenho para a diferença de tempo de execução para a matéria.
23617 Lii

191

Ou com a amada Goiaba :

String[] both = ObjectArrays.concat(first, second, String.class);

Além disso, existem versões para matrizes primitivas:

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

Por mais que eu goste do Guava, o método do Apache Commons lida melhor com os anuláveis.
Ravi Wallau 01/11/13

7
Embora seja bom usar bibliotecas, é lamentável que o problema tenha sido abstraído. Portanto, a solução subjacente permanece ilusória.
user924272

51
Qual é o problema com a abstração? Não sei qual é o problema de reinventar a roda aqui, se você quiser aprender o problema, verifique a fonte ou leia sobre ela. O código profissional deve usar bibliotecas de alto nível, muito melhor se ele for desenvolvido dentro do Google!
Breno Salgado

@RaviWallau Você poderia criar um link para a classe que faz isso?
Sébastien Tromp

1
@ SébastienTromp É a melhor solução para esta pergunta - ArrayUtils.
Ravi Wallau

70

Você pode anexar as duas matrizes em duas linhas de código.

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

Esta é uma solução rápida e eficiente e funcionará para tipos primitivos, bem como os dois métodos envolvidos estão sobrecarregados.

Você deve evitar soluções que envolvam ArrayLists, fluxos etc., pois elas precisarão alocar memória temporária sem nenhum objetivo útil.

Você deve evitar forloops para matrizes grandes, pois elas não são eficientes. Os métodos integrados usam funções de cópia em bloco extremamente rápidas.


1
Esta é uma das melhores soluções. Java 100% padrão. Rápido / eficiente. Deve receber mais votos!
Shebla Tsama

58

Usando a API Java:

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()]);
}

13
Simplesmente, mas ineficiente, pois cria uma matriz para ArrayList e gera outra para o método toArray. Mas ainda é válido, pois é simples de ler.
PhoneixS

1
aplicável para cordas e objetos (como questão quer), mas não há nenhum método addAll de tipos primários (como ints)
Joro

Conforme elaborado neste artigo , o uso both.toArray(new String[0])será mais rápido do que both.toArray(new String[both.size()]), mesmo que contradiga nossa intuição ingênua. É por isso que é tão importante medir o desempenho real ao otimizar. Ou apenas use a construção mais simples, quando a vantagem da variante mais complicada não puder ser comprovada.
Holger

42

Uma solução java 100% antiga e sem System.arraycopy (não disponível no cliente GWT, por exemplo):

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

reformou o meu para File [], mas é o mesmo. Obrigado pela sua solução
ShadowFlame

5
Provavelmente bastante ineficiente.
JonasCz - Reinstate Monica

Você pode querer adicionar nullcheques. E talvez defina algumas de suas variáveis ​​para final.
Tripp Kinetics

As nullverificações do @TrippKinetics ocultariam as NPEs , em vez de mostrá-las, e o uso final de vars locais ainda não tem nenhum benefício.
Maarten Bodewes

1
@Maarten Bodewes Acho que você encontrará (se você fizer o benchmark, o que eu tenho) que o for-each é executado ao mesmo tempo que o loop indexado nas versões mais recentes do Java. O otimizador cuida disso.
Rghome 28/03/19

33

Recentemente, lutei contra problemas com rotação excessiva de memória. Se se sabe que a e / ou b geralmente estão vazios, aqui está outra adaptação do código do silvertab (também gerado):

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: Uma versão anterior deste post afirmou que a reutilização da matriz como esta deve ser claramente documentada. Como Maarten aponta nos comentários, em geral, seria melhor remover as declarações if, anulando assim a necessidade de ter documentação. Mas, novamente, essas instruções if foram o ponto principal dessa otimização específica em primeiro lugar. Vou deixar essa resposta aqui, mas tenha cuidado!


5
no entanto, isso significa que você está retornando a mesma matriz e a alteração de um valor na matriz retornada altera o valor na mesma posição da matriz de entrada retornada.
Lorenzo Boccaccia

Sim - veja o comentário no final do meu post sobre a reutilização da matriz. A sobrecarga de manutenção imposta por esta solução valeu a pena em nosso caso específico, mas a cópia defensiva provavelmente deve ser usada na maioria dos casos.
volley

Lorenzo / vôlei, você pode explicar qual parte do código que causa a reutilização da matriz? Eu pensei que System.arraycopycopia o conteúdo da matriz?
Rosdi Kasim

4
Um chamador normalmente espera que uma chamada para concat () retorne uma matriz recém-alocada. Se a ou b for nulo, concat () retornará uma das matrizes passadas para ele. Essa reutilização é o que pode ser inesperado. (Sim, única arraycopy não copiar o re-uso vem retornando a ou b diretamente..)
volley

O código deve ser o mais auto-explicativo possível. As pessoas que leem o código não precisam procurar o JavaDoc de uma função chamada para descobrir que ele faz uma coisa para uma condição específica e outra para outra. Em resumo: você geralmente não pode corrigir problemas de design como esses com um comentário. Deixar as duas ifdeclarações de fora seria a solução mais fácil.
Maarten Bodewes

27

A biblioteca Java Funcional possui uma classe de wrapper de matriz que equipa as matrizes com métodos úteis, como concatenação.

import static fj.data.Array.array;

...e depois

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

Para recuperar a matriz desembrulhada, chame

String[] s = both.array();

27
ArrayList<String> both = new ArrayList(Arrays.asList(first));
both.addAll(Arrays.asList(second));

both.toArray(new String[0]);

3
A resposta é ótima, mas um pouco quebrada. Para torná-lo perfeito, você deve passar para toArray () uma matriz do tipo que você precisa. No exemplo acima, o código deve ser: both.toArray (nova String [0]) Consulte: stackoverflow.com/questions/4042434/…
Ronen Rabinovici 15/17

Não sei por que esta resposta não é classificado superior ... embora ele não parecem necessitar a mudança sugerida por @RonenRabinovici
drmrbrewer

4
Ou melhor, sem dispêndio desnecessário de matriz de comprimento zero: both.toArray(new String[both.size()]);)
Honza


Oi @Honza, é possível fazer o mesmo para retornar uma matriz inteira primitiva em 3 linhas?
jumping_monkey

18

Outra maneira com Java8 usando 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); 
  }

17

Aqui está uma adaptação da solução da silvertab, com os genéricos adaptados:

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

NOTA: Consulte a resposta de Joachim para obter uma solução Java 6. Não apenas elimina o aviso; também é mais curto, mais eficiente e mais fácil de ler!


Você pode suprimir o aviso para esse método, mas fora isso, não há muito o que fazer. Matrizes e genéricos realmente não se misturam.
Dan Dyer

3
O aviso desmarcado pode ser eliminado se você usar Arrays.copyOf (). Veja minha resposta para uma implementação.
Joachim Sauer

@SuppressWarnings ("desmarcado") #
Mark Renouf

13

Se você usar dessa maneira, não precisará importar nenhuma classe de terceiros.

Se você quer concatenar String

Código de exemplo para 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;
    }

Se você quer concatenar Int

Código de exemplo para 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;
    }

Aqui está o método principal

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

        }
    }  

Também podemos usar esse caminho.


11

Por favor, perdoe-me por adicionar mais uma versão a esta lista já longa. Olhei para todas as respostas e decidi que realmente queria uma versão com apenas um parâmetro na assinatura. Também adicionei uma verificação de argumento para se beneficiar de falhas precoces com informações sensatas em caso de entrada inesperada.

@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;
}

Eu resumiria o comprimento no mesmo loop em que você está fazendo sua verificação nula - mas este é realmente um bom resumo das outras respostas aqui. Eu acredito que ele até lida com tipos intrínsecos como "int" sem alterá-los para objetos Inteiros, que é realmente a ÚNICA razão para lidar com eles como matrizes, em vez de mudar tudo para ArrayLists. Além disso, seu método pode levar 2 matrizes e um parâmetro (...) para que o chamador saiba que precisa passar pelo menos duas matrizes antes de executá-lo e ver o erro, mas isso complica o código de loop ...
Bill K

11

Você pode tentar convertê-lo em uma lista de matriz e usar o método addAll e depois converter novamente em uma matriz.

List list = new ArrayList(Arrays.asList(first));
  list.addAll(Arrays.asList(second));
  String[] both = list.toArray();

Boa solução - seria melhor se o código fosse refatorado para evitar completamente as matrizes em favor de ArrayLists, mas isso está fora do controle da "Resposta" e depende do interlocutor.
Bill K

Eu conto que requer 4 objetos temporários adicionais para funcionar.
Rgome

@ rghome, pelo menos não requer biblioteca adicional para implementar tarefas tão simples
Farid

9

Utilizando fluxos Java 8+, você pode escrever a seguinte função:

private static String[] concatArrays(final String[]... arrays) {
    return Arrays.stream(arrays)
         .flatMap(Arrays::stream)
         .toArray(String[]::new);
}

7

Aqui está uma possível implementação no código de trabalho da solução de pseudocódigo escrita por silvertab.

Obrigado 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;
   }
}

A seguir, é apresentada a interface do construtor.

Nota: Um construtor é necessário porque em java não é possível fazer

new T[size]

devido ao apagamento de tipo genérico:

public interface ArrayBuilderI<T> {

   public T[] build(int size);
}

Aqui, um construtor de concreto implementando a interface, construindo uma Integermatriz:

public class IntegerArrayBuilder implements ArrayBuilderI<Integer> {

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

E finalmente a aplicação / teste:

@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]);
   }
}

7

Isso deve ser one-liner.

public String [] concatenate (final String array1[], final String array2[])
{
    return Stream.concat(Stream.of(array1), Stream.of(array2)).toArray(String[]::new);
}

6

Uau! Muitas respostas complexas aqui, incluindo algumas simples que dependem de dependências externas. Que tal fazer assim:

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

1
..Mas ineficiente e lento.
JonasCz - Restabelece Monica

6

Isso funciona, mas você precisa inserir sua própria verificação de erro.

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

Provavelmente não é o mais eficiente, mas não depende de nada além da própria API do Java.


2
+1. Seria melhor substituir o segundo forloop por aquele:for(int j = 0; j < arr2.length; j++){arrBoth[arr1.length+j] = arr2[j];}
bancer 28/10/10

Use String[] arrBoth = java.util.Arrays.copyOf(arr1, arr1.length + arr2.length)para pular o primeiro forloop. Economiza tempo proporcional ao tamanho de arr1.
John Meyer

5

Esta é uma função convertida para uma matriz String:

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

5

Que tal simplesmente

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

E apenas faça Array.concat(arr1, arr2). Contanto que arr1e arr2sejam do mesmo tipo, isso fornecerá outra matriz do mesmo tipo contendo as duas matrizes.


Por motivos de desempenho, eu pré-calculava o tamanho final do ArrayList porque ArrayList, por definição, aloca um novo array e copia seus elementos sempre que o array atual estiver cheio. Caso contrário, eu iria direto para LinkedList que não sofre esse problema
ΕΨΗΕΛΩΝ usr-local-

5

Uma versão estática genérica que usa o System.arraycopy de alto desempenho sem exigir uma anotação @SuppressWarnings:

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

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

4

Aqui está minha versão ligeiramente melhorada do concatAll de Joachim Sauer. Ele pode funcionar no Java 5 ou 6, usando System.arraycopy do Java 6, se estiver disponível em tempo de execução. Esse método (IMHO) é perfeito para o Android, pois funciona no Android <9 (que não possui System.arraycopy), mas utilizará o método mais rápido, se possível.

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

1
Boa ideia geral, mas a qualquer pessoa que esteja implementando: eu preferiria versões copyOf e non-copyOf do que uma que faça as duas coisas como reflexo.
Re

4

Outra maneira de pensar sobre a questão. Para concatenar duas ou mais matrizes, é necessário listar todos os elementos de cada matriz e criar uma nova matriz. Parece criar um List<T>e, em seguida, chama toArray. Algumas outras respostas usam ArrayList, e isso é bom. Mas que tal implementar a nossa? Não é difícil:

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

Eu acredito que o acima é equivalente a soluções que usa System.arraycopy. No entanto, acho que este tem sua própria beleza.


4

E se :

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

Uma variação simples que permite a junção de mais de uma matriz:

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()]);
}

3

Usando apenas a API própria do Javas:


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

Agora, esse código não é o mais eficiente, mas depende apenas de classes java padrão e é fácil de entender. Funciona para qualquer número de String [] (mesmo zero matrizes).


15
Teve que reduzir a votação deste para toda a criação desnecessária de objetos de lista.
Outlaw Programmer
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.