Java에서 두 개의 배열을 어떻게 연결할 수 있습니까?


1366

StringJava에서 두 개의 배열 을 연결해야합니다 .

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

가장 쉬운 방법은 무엇입니까?


3
구아바에서 Bytes.concat
벤 페이지

1
나는 여기에 많은 답변을 보았지만 가장 좋은 대답을 표시 할 수 없을 정도로 질문은 '가장 쉬운 방법?'입니다.
Artur Opalinski

2
여기에 수십 개의 답변이 데이터를 새로운 배열로 복사하고 있습니다. 왜냐하면 그것이 요구 된 것이기 때문입니다. 그러나 엄격하게 필요하지 않을 때 데이터를 복사하는 것은 특히 Java에서 나쁜 일입니다. 대신 인덱스를 추적하고 두 배열을 마치 결합 된 것처럼 사용하십시오. 이 기술을 설명하는 솔루션을 추가했습니다.
Douglas

12
이와 같은 질문에 현재 50 가지 답변이 있다는 사실 때문에 Java가 왜 간단한 array1 + array2연결을 얻지 못했는지 궁금 합니다.
JollyJoker

2
표준 Java의 두 줄로 완벽하고 효율적으로 할 수 있으므로 (내 답변 참조) 단일 방법으로 수행하면 얻을 수있는 많은 것이 없습니다. 이 이상하고 놀라운 솔루션은 모두 약간의 시간 낭비입니다.
rghome

답변:


1093

좋은 오래된 Apache Commons Lang 라이브러리에서 한 줄 솔루션을 찾았습니다.
ArrayUtils.addAll(T[], T...)

암호:

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

175
질문에 대답하면 어떻게 "속임수"입니까? 물론, 특정 상황에서는 추가적인 의존성을 갖는 것이 과도 할 수 있지만, 특히 Apache Commons에는 매우 뛰어난 기능이 있기 때문에 존재한다는 사실을 알리는 데 아무런 해가 없습니다.
Rob

33
나는 이것이 실제로 질문에 대답하지 않는다는 것에 동의합니다. 높은 수준의 라이브러리는 훌륭 할 수 있지만 효율적인 방법을 배우려면 라이브러리 방법에서 사용하는 코드를보고 싶을 것입니다. 또한 많은 상황에서 제품의 다른 라이브러리를 즉시 사용할 수 없습니다.
AdamC

76
나는 이것이 좋은 대답이라고 생각합니다. POJO 솔루션도 제공되었지만 OP가 프로그램에서 Apache Commons를 이미 사용하고 있다면 (그 인기를 고려하면 가능할 수 있음) 그는 여전히이 솔루션을 알지 못할 수 있습니다. 그런 다음 "이 한 가지 방법에 대한 종속성을 추가하는"것이 아니라 기존 라이브러리를 더 잘 활용할 것입니다.
Adam

14
단일 방법으로 라이브러리를 추가하지 않을 것을 항상 걱정한다면 새 라이브러리는 추가되지 않습니다. Apache Commons에 우수한 유틸리티가 있으므로 처음 사용하는 경우 추가하는 것이 좋습니다.
Hindol

6
아파치 커먼즈를 사용하는 것을 절대로 '부정 행위'라고해서는 안됩니다. 불필요한 의존성을 가진 개발자의 정신에 의문을 제기합니다.
제릴 쿡

768

다음은 두 배열을 연결하고 결과를 반환하는 간단한 방법입니다.

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

기본 데이터 유형에서는 작동하지 않으며 오브젝트 유형에서만 작동합니다.

다음과 같이 약간 더 복잡한 버전은 객체 및 기본 배열 모두에서 작동합니다. 인수 유형 T대신 사용하여이를 수행 T[]합니다.

또한 가장 일반적인 유형을 결과의 구성 요소 유형으로 선택하여 두 가지 유형의 배열을 연결할 수 있습니다.

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

예를 들면 다음과 같습니다.

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
이 제안은 최신 Java 버전에 덜 의존하기 때문에이 제안을 좋아합니다. 내 프로젝트에서 종종 Antti가 언급 한 것과 같은 일부 기능을 사용할 수없는 이전 버전의 Java 또는 CLDC 프로파일을 사용하고 있습니다.
kvn

4
다음 줄은 일반적인 부분을 깰 것입니다 : concatenate (new String [] { "1"}, new Object [] {new Object ()})
dragon66

@SuppressWarnings 주석을 사용할 필요가 없습니다-아래에 그 해결책을 게시 할 것입니다.
beaudet

일에 대한 Array.newInstance(a.getClass().getComponentType(), aLen + bLen);. 놀랍게도 전에는 본 적이 없습니다. @beaudet 왜 주석이 억제되는지를 고려하여 주석이 훌륭하다고 생각합니다.
Blake

1
하, 순수 주의자라고 부르지 만 경고를 제거하기 위해 경고를 억제하지 않아도되는 깨끗한 코드를 선호합니다.
beaudet

475

여러 배열을 연결하도록 확장 할 수있는 완전 일반 버전을 작성할 수 있습니다. 이 버전은 Java 6을 사용하므로 필요합니다.Arrays.copyOf()

두 버전 모두 중개 List오브젝트를 작성하지 않고 System.arraycopy()대형 어레이를 최대한 빨리 복사 하는 데 사용 합니다.

두 배열의 경우 다음과 같습니다.

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

그리고 임의의 수의 배열 (> = 1)의 경우 다음과 같습니다.

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 : 기본 유형 배열의 경우 각 유형에 대해 과부하를 만들어야합니다. 코드를 복사하고 각각을 T로 바꾸십시오 byte(및을 잃음 <T>).
Joachim Sauer 2018 년

수업 시간에 <T> 연산자 유형을 사용하는 방법을 알려주시겠습니까?
Johnydep

6
나는 이것을 방어에 집중하기 위해 처음에 추가 할 것입니다. if (first == null) {if (second == null) {리턴 널; } 둘째 반환; } if (second == null) {먼저 리턴; }
마라톤

4
@djBo : 어떻습니까 :ByteBuffer buffer = ByteBuffer.allocate(array1.length + array2.length); buffer.put(array1); buffer.put(array2); return buffer.array();
Sam Goldberg

18
이 접근 방식에는 버그 가 있습니다. 예를 들어 concat(ai, ad)where aiis Integer[]and adis 와 같이 다른 구성 요소 유형의 배열로 이러한 함수를 호출하면 분명해집니다 Double[]. (이 경우, type 매개 변수 <T><? extends Number>컴파일러 에 의해 해석됩니다 .)로 작성된 Arrays.copyOf배열은 첫 번째 배열의 구성 요소 유형 (예 : Integer이 예) 을 갖습니다 . 함수가 두 번째 배열을 복사하려고 ArrayStoreException할 때가 발생합니다. 해결책은 추가 Class<T> type매개 변수를 갖는 것 입니다.
T-Bull

457

StreamJava 8에서 사용 :

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

또는 다음과 같이 사용하십시오 flatMap.

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

제네릭 형식에 대해 이렇게하려면 리플렉션을 사용해야합니다.

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

28
이것이 얼마나 효율적입니까?
Supuhstar

8
읽을만한 가치가있는 : jaxenter.com/… tl; 스트림은 성능이 수도 있고 그렇지 않을 수도 있습니다. 스트림이 수행하는 작업과 문제의 제약에 따라 다릅니다 (항상 답이 아닙니까? lol)
Trevor Brown

6
또한, a 또는 b 가 기본 유형의 배열 인 경우 스트림은 예 를 들어 에 매개 변수로 전달할 수없는 .boxed()유형 Stream이어야 IntStream합니다 Stream.concat.
Will Hardwick-Smith

17
@Will Hardwick-Smith : 아니요, 올바른 스트림 클래스 만 선택하면됩니다 (예 : if aand bare int[])int[] both = IntStream.concat(Arrays.stream(a), Arrays.stream(b)).toArray();
Holger

3
@Supuhstar : 아마 빠르지 않을 것입니다 System.arrayCopy. 그러나 특히 느리지는 않습니다. 당신은 아마 이것을을해야 할 매우 많은 시간 거대한 에 배열을 정말 중요 할 수있는 실행 시간 차이의 성능에 민감한 상황.
Lii

191

또는 사랑하는 구아바 와 함께 :

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

또한 기본 배열의 버전이 있습니다.

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

구아바를 좋아하는 한 Apache Commons의 방법은 nullable을 더 잘 처리합니다.
Ravi Wallau

7
라이브러리를 사용하는 것이 좋지만 문제가 해결 된 것은 유감입니다. 따라서 근본적인 해결책은 찾기 쉽지 않습니다.
user924272

51
추상화의 문제점은 무엇입니까? Dunno 휠을 재발 명하는 문제는 무엇입니까? 문제를 배우고 싶다면 소스를 확인하거나 읽으십시오. 전문 코드는 고급 라이브러리를 사용해야합니다 .Google에서 개발하면 훨씬 좋습니다!
Breno Salgado

@RaviWallau이 작업을 수행하는 클래스에 연결할 수 있습니까?
Sébastien Tromp

1
@ SébastienTromp이 질문에 대한 최상의 솔루션은 ArrayUtils입니다.
라비 Wallau

70

두 줄의 코드로 두 배열을 추가 할 수 있습니다.

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

이 방법은 빠르고 효율적인 솔루션이며 기본 유형과 관련된 두 가지 방법이 모두 오버로드 될 수 있습니다.

유용한 목적없이 임시 메모리를 할당해야하므로 ArrayList, 스트림 등과 관련된 솔루션은 피해야합니다.

for큰 배열에는 효율적이지 않으므로 루프를 피해야 합니다. 내장 된 메소드는 매우 빠른 블록 복사 기능을 사용합니다.


1
이것은 최고의 솔루션 중 하나입니다. 100 % 표준 Java. 빠르고 효율적입니다. 더 많은 투표를해야한다!
Shebla Tsama

58

Java API 사용 :

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
ArrayList에 대한 배열을 만든 다음 toArray 메소드에 대한 다른 배열을 생성하므로 간단하지만 비효율적입니다. 그러나 읽기 쉽지만 여전히 유효합니다.
PhoneixS

1
문자열과 객체에 적용 가능하지만 (질문과 같은) 기본 유형에 대한 addAll 메소드는 없습니다 (int).
joro

로가에 정교 이 문서 사용하여 both.toArray(new String[0])보다 빠른 것 both.toArray(new String[both.size()])이 우리의 순진 직관 모순하더라도. 따라서 최적화 할 때 실제 성능을 측정하는 것이 중요합니다. 또는 더 복잡한 변형의 이점을 입증 할 수없는 경우 더 간단한 구성을 사용하십시오.
Holger

42

100 % 오래된 Java없는 솔루션 System.arraycopy(예 : GWT 클라이언트에서는 사용할 수 없음) :

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

File []에 대한 광산을 재 작업했지만 동일합니다. 솔루션 주셔서 감사합니다
ShadowFlame

5
아마 상당히 비효율적입니다.
JonasCz-복원 모니카

null검사 를 추가 할 수 있습니다 . 그리고 일부 변수를로 설정하십시오 final.
Tripp Kinetics

@TrippKinetics null검사는 NPE를 표시하지 않고 숨길 수 있으며 지역 변수에 final을 사용하면 아무런 이점이 없습니다.
Maarten Bodewes

1
@Maarten Bodewes for-each가 최신 버전의 Java에서 인덱스 루프와 동시에 실행된다는 것을 알게 될 것입니다. 옵티마이 저가 처리합니다.
rghome

33

최근에 과도한 메모리 회전 문제가 발생했습니다. a 및 / 또는 b가 일반적으로 비어있는 것으로 알려진 경우 다음은 silvertab 코드의 또 다른 적응입니다 (일반적으로 생성됨).

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

편집 :이 게시물의 이전 버전은 이와 같은 배열 재사용이 명확하게 문서화되어야한다고 언급했습니다. Maarten이 의견에서 지적한 것처럼 일반적으로 if 문을 제거하는 것이 더 좋으므로 문서화가 필요하지 않습니다. 그러나 다시 한 번 if 문은이 특정 최적화의 요점이었습니다. 이 답변을 여기에 남겨 둘 것이지만 조심하십시오!


5
그러나 이는 동일한 배열을 반환하고 반환 된 배열의 값을 변경하면 반환 된 입력 배열의 동일한 위치에서 값이 변경됨을 의미합니다.
Lorenzo Boccaccia

예-내 게시물 끝에 배열 재사용에 관한 의견을 참조하십시오. 이 솔루션에 의해 부과 된 유지 관리 오버 헤드는 우리의 특별한 경우에 그만한 가치가 있었지만, 대부분의 경우 방어 적 복사가 사용될 것입니다.
Volley

Lorenzo / 발리, 코드에서 배열 재사용을 유발하는 부분을 설명 할 수 있습니까? System.arraycopy배열의 내용을 복사 한다고 생각 했습니까?
Rosdi Kasim

4
호출자는 일반적으로 concat () 호출로 새로 할당 된 배열을 반환합니다. a 또는 b가 null이면 concat ()은 전달 된 배열 중 하나를 반환합니다. 이 재사용은 예상치 못한 것일 수 있습니다. (예, arraycopy는 복사 만합니다. 재사용은 a 또는 b를 직접 반환하여 제공됩니다.)
volley

코드는 가능한 한 많은 설명이 필요합니다. 코드를 읽는 사람들은 호출 된 함수의 JavaDoc을 조회하여 특정 조건에 대해 한 가지 일과 다른 조건에 대해 다른 일을하는 것을 찾을 필요가 없습니다. 간단히 말해서 일반적으로 주석과 같은 디자인 문제를 해결할 수는 없습니다. 두 if문장을 남기는 것이 가장 쉬운 해결책입니다.
Maarten Bodewes

27

기능성 자바 라이브러리 연결과 같은 간편한 방법과 배열을 갖추고있다 배열 래퍼 클래스를 가지고있다.

import static fj.data.Array.array;

...그리고

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

래핑되지 않은 배열을 다시 불러 오려면

String[] s = both.array();

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

both.toArray(new String[0]);

3
대답은 훌륭하지만 조금 깨졌습니다. 완벽하게하려면 필요한 유형의 배열을 toArray ()에 전달해야합니다. 위 예제에서 코드는 다음과 같아야합니다. both.toArray (new String [0]) 참조 : stackoverflow.com/questions/4042434/…
Ronen Rabinovici

왜이 답변이 더 높은 등급을받지 않았는지 모릅니다. @RonenRabinovici가 제안한 변경이 필요한 것 같습니다
drmrbrewer

4
또는 길이가 0 인 배열을 불필요하게 할당하지 않으면 더 좋습니다. both.toArray(new String[both.size()]);)
Honza

1
@ Honza 권장 읽기
Holger

안녕하세요 @ Honza, 프리미티브 정수 배열을 3 줄로 반환하기 위해 동일한 작업을 수행 할 수 있습니까?
jumping_monkey

18

Stream을 사용하는 Java8의 또 다른 방법

  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

다음은 제네릭이 개선 된 silvertab 솔루션의 적응입니다.

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

참고 : Java 6 솔루션에 대한 Joachim의 답변 을 참조하십시오 . 경고를 제거 할뿐만 아니라; 또한 짧고 효율적이며 읽기 쉽습니다!


이 방법에 대한 경고를 표시하지 않아도 할 수있는 것 외에는 할 수 없습니다. 배열과 제네릭은 실제로 혼합되지 않습니다.
Dan Dyer

3
Arrays.copyOf ()를 사용하면 확인되지 않은 경고를 제거 할 수 있습니다. 구현에 대한 내 대답을 참조하십시오.
Joachim Sauer

@SuppressWarnings ( "checked")
Mark Renouf

13

이 방법을 사용하면 타사 클래스를 가져올 필요가 없습니다.

연결을 원한다면 String

두 개의 문자열 배열을 연결하기위한 샘플 코드

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

연결을 원한다면 Int

두 정수 배열을 연결하기위한 샘플 코드

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

주요 방법은 다음과 같습니다

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

        }
    }  

이 방법으로도 사용할 수 있습니다.


11

이 긴 목록에 다른 버전을 추가해 주셔서 감사합니다. 나는 모든 대답을보고 서명에 매개 변수가 하나 뿐인 버전을 정말로 원한다고 결정했습니다. 또한 예기치 않은 입력의 경우 현명한 정보로 조기 실패의 이점을 얻기 위해 인수 검사를 추가했습니다.

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

null 확인을 수행하는 동일한 루프에서 길이를 요약하지만 여기에있는 다른 답변에 대한 요약입니다. Integer 객체로 변경하지 않고 "int"와 같은 내장 유형을 처리한다고 생각합니다. 이는 모든 것을 ArrayLists로 변경하는 것이 아니라 배열로 처리 해야하는 유일한 이유입니다. 또한 메소드는 2 개의 배열과 (...) 매개 변수를 사용할 수 있으므로 호출자는 실행하기 전에 적어도 두 개의 배열을 전달해야하고 오류를 보지만 루프 코드를 복잡하게 만드는 것을 알 수 있습니다 ....
Bill K

11

Arraylist로 변환하고 addAll 메소드를 사용한 다음 다시 배열로 변환 할 수 있습니다.

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

좋은 해결책-ArrayLists에 찬성하여 배열을 피하기 위해 코드를 리팩토링하면 더 좋을 것입니다.
Bill K

작동하려면 4 개의 추가 임시 개체가 필요하다고 생각합니다.
rghome

@rghome, 최소한 그러한 간단한 작업을 구현하기 위해 추가 라이브러리가 필요하지 않습니다
Farid

9

Java 8+ 스트림을 사용하여 다음 기능을 작성할 수 있습니다.

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

7

여기 실버 탭이 작성한 의사 코드 솔루션의 작업 코드에서 가능한 구현입니다.

고마워 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;
   }
}

다음은 빌더 인터페이스입니다.

참고 : Java에서는 수행 할 수 없으므로 빌더가 필요합니다.

new T[size]

일반 유형 삭제로 인해 :

public interface ArrayBuilderI<T> {

   public T[] build(int size);
}

다음은 인터페이스를 구현하고 Integer배열을 작성 하는 콘크리트 빌더입니다 .

public class IntegerArrayBuilder implements ArrayBuilderI<Integer> {

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

그리고 마지막으로 응용 프로그램 / 테스트 :

@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

이것은 하나의 라이너 여야합니다.

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

6

와! 외부 의존성에 의존하는 간단한 답변을 포함하여 여기에 많은 복잡한 답변이 있습니다. 이렇게하면 어떻습니까?

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
.. 그러나 비효율적이고 느리다.
JonasCz-복원 모니카

6

작동하지만 자체 오류 검사를 삽입해야합니다.

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

아마도 가장 효율적인 것은 아니지만 Java 자체 API 이외의 것에 의존하지 않습니다.


2
+1. 두 번째 for루프를 다음과 같이 바꾸는 것이 좋습니다 .for(int j = 0; j < arr2.length; j++){arrBoth[arr1.length+j] = arr2[j];}
bancer

String[] arrBoth = java.util.Arrays.copyOf(arr1, arr1.length + arr2.length)첫 번째 for루프 를 건너 뛰는 데 사용 합니다 . 의 크기에 비례하여 시간을 절약합니다 arr1.
John Meyer

5

이것은 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

어때요?

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

그리고 그냥하세요 Array.concat(arr1, arr2). 만큼 arr1arr2같은 유형이다, 이것은 당신에게 두 배열을 포함하는 동일한 유형의 다른 배열을 줄 것이다.


성능상의 이유로 ArrayList는 정의에 따라 현재 배열이 가득 찰 때마다 새 배열을 할당하고 해당 요소를 복사하기 때문에 ArrayList의 최종 크기를 미리 계산합니다. 그렇지 않으면 나는 그런 문제를 겪지 않는 LinkedList를 위해 곧장 갈 것이다
usr-local-ΕΨΗΕΛΩΝ

5

@SuppressWarnings 주석없이 고성능 System.arraycopy를 사용하는 일반 정적 버전 :

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

여기 Joachim Sauer의 concatAll의 약간 개선 된 버전이 있습니다. 런타임에 사용 가능한 경우 Java 6의 System.arraycopy를 사용하여 Java 5 또는 6에서 작동 할 수 있습니다. 이 방법 (IMHO)은 Android <9 (System.arraycopy가없는)에서 작동하지만 가능한 경우 더 빠른 방법을 사용하므로 Android에 적합합니다.

  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
좋은 일반적인 아이디어이지만 구현하는 모든 사람에게 : 나는 리플렉션 방식으로 수행하는 것보다 copyOf 및 non-copyOf 버전을 선호합니다.
rektide

4

질문에 대해 생각하는 또 다른 방법. 둘 이상의 배열을 연결하려면 각 배열의 모든 요소를 ​​나열한 다음 새 배열을 작성해야합니다. 이것은 a List<T>를 만든 다음 호출 하는 것처럼 들립니다 toArray. 다른 답변은을 사용 ArrayList하며 괜찮습니다. 그러나 우리 자신의 구현은 어떻습니까? 어렵지 않다 :

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

위의 내용은 사용하는 솔루션과 동일하다고 생각합니다 System.arraycopy. 그러나 나는 이것이 하나의 아름다움을 가지고 있다고 생각합니다.


4

어때요?

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

둘 이상의 배열을 결합 할 수있는 간단한 변형 :

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

Java 자체 API 만 사용 :


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

이 코드는 가장 효율적이지는 않지만 표준 Java 클래스에만 의존하며 이해하기 쉽습니다. 임의의 수의 String [] (제로 배열)에서도 작동합니다.


15
모든 불필요한 List 객체 생성을 위해 이것을 하향 투표했습니다.
무법자 프로그래머
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.