Java에서 String
배열을 연결해야 합니다.
void f(String[] first, String[] second) { String[] both = ??? }
이 작업을 수행하는 가장 쉬운 방법은 무엇입니까?
질문자 :Community Wiki
Java에서 String
배열을 연결해야 합니다.
void f(String[] first, String[] second) { String[] both = ??? }
이 작업을 수행하는 가장 쉬운 방법은 무엇입니까?
좋은 오래된 Apache Commons Lang 라이브러리에서 한 줄 솔루션을 찾았습니다.
ArrayUtils.addAll(T[], T...)
암호:
String[] both = ArrayUtils.addAll(first, second);
다음은 두 개의 배열을 연결하고 결과를 반환하는 간단한 방법입니다.
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 }));
Java 8에서 Stream
사용:
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));
모든 배열을 연결하도록 확장할 수 있는 완전히 일반적인 버전을 작성하는 것이 가능합니다. Arrays.copyOf()
를 사용하므로 Java 6이 필요합니다.
두 버전 모두 중간 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; }
또는 사랑하는 구아바 와 함께:
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)
두 줄의 코드에 두 개의 배열을 추가할 수 있습니다.
String[] both = Arrays.copyOf(first, first.length + second.length); System.arraycopy(second, 0, both, first.length, second.length);
이것은 빠르고 효율적인 솔루션이며 기본 유형과 관련된 두 가지 방법이 오버로드된 경우에도 작동합니다.
ArrayList, 스트림 등과 관련된 솔루션은 유용한 목적 없이 임시 메모리를 할당해야 하므로 피해야 합니다.
큰 배열에 대해서는 효율적이지 않으므로 for
루프를 피해야 합니다. 내장 메소드는 매우 빠른 블록 복사 기능을 사용합니다.
자바 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()]); }
System.arraycopy
없는 100% 오래된 Java 솔루션(예: 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; }
나는 최근에 과도한 메모리 회전 문제와 싸웠습니다. 및/또는 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 문은 처음에 이 특정 최적화의 요점이었습니다. 이 답변을 여기에 남길 것이지만 조심하십시오!
Functional Java 라이브러리에는 배열에 연결과 같은 편리한 방법을 제공하는 배열 래퍼 클래스가 있습니다.
import static fj.data.Array.array;
...그리고
Array<String> both = array(first).append(array(second));
래핑되지 않은 배열을 다시 꺼내려면 다음을 호출하십시오.
String[] s = both.array();
ArrayList<String> both = new ArrayList(Arrays.asList(first)); both.addAll(Arrays.asList(second)); both.toArray(new String[0]);
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); }
다음은 제네릭을 개조한 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의 답변을 참조하십시오. 경고를 제거할 뿐만 아니라; 또한 더 짧고 효율적이며 읽기 쉽습니다!
Arraylist로 변환하고 addAll 메서드를 사용한 다음 다시 배열로 변환할 수 있습니다.
List list = new ArrayList(Arrays.asList(first)); list.addAll(Arrays.asList(second)); String[] both = list.toArray();
이 방법을 사용하면 타사 클래스를 가져올 필요가 없습니다.
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; }
다음은 Main 메서드입니다.
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)); } }
우리도 이 방법을 사용할 수 있습니다.
이미 긴 목록에 다른 버전을 추가한 것을 용서해 주십시오. 모든 답변을 살펴보고 서명에 매개변수가 하나만 있는 버전을 원한다고 결정했습니다. 또한 예상치 못한 입력의 경우에 합리적인 정보로 조기 실패의 이점을 얻기 위해 몇 가지 인수 검사를 추가했습니다.
@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; }
Java 8+ 스트림을 사용하여 다음 함수를 작성할 수 있습니다.
private static String[] concatArrays(final String[]... arrays) { return Arrays.stream(arrays) .flatMap(Arrays::stream) .toArray(String[]::new); }
다음은 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; } }
다음은 빌더 인터페이스입니다.
참고: 자바에서는 할 수 없기 때문에 빌더가 필요합니다.
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]); } }
이것은 한 줄로 되어 있어야 합니다.
public String [] concatenate (final String array1[], final String array2[]) { return Stream.concat(Stream.of(array1), Stream.of(array2)).toArray(String[]::new); }
우와! 여기에는 외부 종속성에 의존하는 몇 가지 간단한 답변을 포함하여 복잡한 답변이 많이 있습니다. 다음과 같이 하면 어떻습니까?
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]);
이것은 작동하지만 고유한 오류 검사를 삽입해야 합니다.
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 이외의 다른 것에 의존하지 않습니다.
이것은 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; }
간단히 어떻습니까
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)
하세요. arr1
과 arr2
가 같은 유형이면 두 배열을 모두 포함하는 동일한 유형의 다른 배열이 제공됩니다.
둘 이상의 배열을 결합할 수 있는 간단한 변형:
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()]); }
@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; }
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[](심지어 0개의 배열도 포함)에 대해 작동합니다.
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; }
다음은 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; }
질문에 대해 생각하는 또 다른 방법입니다. 두 개 이상의 배열을 연결하려면 각 배열의 모든 요소를 나열한 다음 새 배열을 작성해야 합니다. 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
를 사용하는 솔루션과 동일하다고 생각합니다. 하지만 이것도 나름의 아름다움이 있는 것 같아요.
어때요:
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()]); }
출처 : http:www.stackoverflow.com/questions/80476/how-can-i-concatenate-two-arrays-in-java
jQuery를 사용하여 요소의 ID를 어떻게 얻을 수 있습니까? (0) | 2022.02.24 |
---|---|
Python이 이 JSON 데이터를 구문 분석할 수 없는 이유는 무엇입니까? (0) | 2022.02.24 |
Chrome에서 자체 서명된 로컬 호스트 인증서를 수락하도록 하기 (0) | 2022.02.24 |
C#에서 클래스 대신 구조체를 사용해야 하는 경우는 언제인가요? (0) | 2022.02.24 |
Node.js를 완전히 제거하고 처음부터 다시 설치하는 방법(Mac OS X) (0) | 2022.02.24 |