컬렉션을 배열로 변환하는 가장 쉬운 방법은 무엇입니까?


125

우리가 Collection<Foo>. 그것을 변환하는 가장 좋은 (현재 컨텍스트에서 LoC에서 가장 짧은) 방법은 Foo[]무엇입니까? 어떤은 잘 알려진 라이브러리를 사용할 수 있습니다.

UPD :; : 어떤 변화에 대해 (이 부분에서 또 하나의 사례 휴가 코멘트 당신은 그것의 가치는 그것을 위해 다른 스레드를 만들 생각하는 경우) Collection<Foo>Bar[]어디 Bar유형의 한 매개 변수를 생성자가 Foopublic Bar(Foo foo){ ... }?


비슷한 성능으로 동일한 작업을 수행하고 설명과 함께 JDK-11에 도입 된 대체 API 로이 답변 을 작성했습니다. 또한 구문 Stream.toArray은 JDK 의 기존 API 와 일치합니다 .
Naman

답변:


256

x컬렉션은 어디에 있습니까?

Foo[] foos = x.toArray(new Foo[x.size()]);

35
더 간단 하지만 (쉬움) 최고는 아닙니다 (메모리) : x.toArray(new Foo[0]) --- 문서 : 읽을 시간 없음 ...
user85421

6
@Carlos는 실제로 (new Foo[0]). Collection.toArray 문서에 따르면`@param a이 컬렉션의 요소가 저장 될 배열입니다. 충분히 크면 새 배열에 직접 저장할 것입니다. 크기 0 배열을 지정하면 새 배열이 만들어집니다. 즉, 작은 배열과 불필요한 경우 큰 배열이 만들어집니다.
corsiKa 2010

4
@glowcoder-하지만 빈 배열을 정적 상수로 한 번 정의하면 최소화 할 수 있습니다. toArray올바른 유형의 대상 배열을 생성하기 위한 힌트 일뿐 입니다. 그리고이 경우 솔직히 내 응용 프로그램에서 하나의 추가 빈 배열에 대해 신경 쓰지 않을 것입니다. 소음 수준보다 훨씬 낮습니다.
Andreas Dolk

2
@glowcoder - 나는 (그 이유는 정확히 으로 시도 )를 사용하여 썼다 new Foo[0]간단하다 "최고 (메모리)하지만"... 즉, 나는 내 솔루션을 쉽게하지만 것을 의미하지 않는 것이 좋습니다 (내가 사용하는 이유의 그 :).
user85421 jul.

21
이 코드는 동기화 된 컬렉션을 사용하는 경우에도 스레드 세이프가 아닙니다. 대부분의 상황에서 자체적으로 작동하지만 x.size () 및 x.toArray () 호출 사이에 항목이 삭제되면 결과 배열의 끝에 추가 null 요소가 포함됩니다. new Foo[0]카를로스에 의해 제안 된 변형은이 문제를 겪지 않는다.
Jules

36

Java 8을 사용하여 업데이트 된 질문에 대한 대체 솔루션 :

Bar[] result = foos.stream()
    .map(x -> new Bar(x))
    .toArray(size -> new Bar[size]);

35
이것은 단축 될 수 있습니다 Bar[] result = foos.stream().map(Bar::new).toArray(Bar[]::new);
lpandzic dec

구문 현명한 나는 받아 들여지는 대답을 훨씬 선호합니다. 사람들이 모두 파이썬으로 전환 할 수 있기를 바랍니다.
에릭 첸

@EricChen Python으로 전환-자바에서 해석되고 동적으로 입력되는 언어-코딩 구문과 숫자 행이 다르기 때문에 '컴파일되고 정적으로 입력 된 언어'? 좋은 생각이 아닙니다.
RafiAlhamd

10

두 번 이상 사용하거나 루프에서 사용하는 경우 상수를 정의 할 수 있습니다.

public static final Foo[] FOO = new Foo[]{};

다음과 같은 변환을 수행하십시오.

Foo[] foos = fooCollection.toArray(FOO);

toArray메서드는 빈 배열을 사용하여 대상 배열의 올바른 유형을 결정하고 새 배열을 만듭니다.


업데이트에 대한 제 제안은 다음과 같습니다.

Collection<Foo> foos = new ArrayList<Foo>();
Collection<Bar> temp = new ArrayList<Bar>();
for (Foo foo:foos) 
    temp.add(new Bar(foo));
Bar[] bars = temp.toArray(new Bar[]{});

1
ups, constJava가 아닙니다! public static final Foo[] FOO = {}
user85421 2010-07-20

1
왜 공개 될까요?
Zoltán 2013

@ Zoltán-왜 안돼? 불변이므로 안전 문제가 없습니다. 약간 어수선하지만 다른 코드에서 유용 할 수 있으므로 일반적으로 무해합니다. 이 모든 상수를 사용 import static하여 중앙 클래스를 만든 다음이를 사용 하여 얻을 수도 있습니다.
Jules

@Jules 배열에 대한 참조는 변경 불가능하지만 그 내용은 변경되지 않습니다. 클래스 외부의 모든 사용자가 배열의 요소를 자유롭게 바꿀 수 있습니다. 한편, 경험상 모든 필드는 클래스 외부에서 필요할 때까지 비공개로 만들어야한다고 생각합니다.
Zoltán

2
길이가 0이므로 변경할 수있는 내용이 없습니다.
Jules

5

JDK / 11에서 a Collection<Foo>를 로 변환하는 다른 방법은 다음 Foo[]Collection.toArray(IntFunction<T[]> generator)같이 사용하는 것입니다.

Foo[] foos = fooCollection.toArray(new Foo[0]); // before JDK 11
Foo[] updatedFoos = fooCollection.toArray(Foo[]::new); // after JDK 11

에 의해 설명으로 메일 링리스트에 @Stuart (강조 광산), 이것의 성능은 기본적으로 기존의 것과 동일해야합니다 Collection.toArray(new T[0])-

결론적으로 그 구현이 사용하는 것입니다 Arrays.copyOf() 아마 때문에 가장 빠르다 는 고유이다 .

전체 배열 내용을 덮어 쓸 것임을 알고 있기 때문에 새로 할당 된 배열을 0으로 채우는 것을 방지 할 수 있습니다. 이는 공개 API가 어떻게 생겼는지에 관계없이 사실입니다.

JDK 내의 API 구현은 다음과 같습니다.

default <T> T[] toArray(IntFunction<T[]> generator) {
    return toArray(generator.apply(0));
}

기본 구현은 generator.apply(0)길이가 0 인 배열을 가져 오기 위해 호출 한 다음 단순히 toArray(T[]). 이것은 Arrays.copyOf() 빠른 경로 를 통과 하므로 기본적으로 toArray(new T[0]).


참고 :-값이있는코드에 사용할 때API 사용은 이전 버전 과의 비 호환성 과 함께 안내되어야null합니다. 예를 들어toArray(null)이러한 호출은 기존 때문에 모호toArray(T[] a)하고 컴파일에 실패하기때문입니다.



3

원본의 경우 이중 답변을 참조하십시오 .

Foo[] a = x.toArray(new Foo[x.size()]);

업데이트에 관해서 :

int i = 0;
Bar[] bars = new Bar[fooCollection.size()];
for( Foo foo : fooCollection ) { // where fooCollection is Collection<Foo>
    bars[i++] = new Bar(foo);
}    

3

다음은 업데이트 섹션의 사례에 대한 최종 솔루션입니다 (Google 컬렉션의 도움으로).

Collections2.transform (fooCollection, new Function<Foo, Bar>() {
    public Bar apply (Foo foo) {
        return new Bar (foo);
    }
}).toArray (new Bar[fooCollection.size()]);

그러나 여기서 핵심 접근 방식 은 doublep의 답변 에서 언급되었습니다 (나는 toArray방법을 잊었습니다 ).


1
이 솔루션에도 적용되는 스레드 안전성에 대한 doublep의 답변에 대한 내 의견을 참조하십시오. new Bar[0]문제를 피합니다.
Jules

-1

예를 들어 Student 클래스 요소가있는 컬렉션 ArrayList가 있습니다.

List stuList = new ArrayList();
Student s1 = new Student("Raju");
Student s2 = new Student("Harish");
stuList.add(s1);
stuList.add(s2);
//now you can convert this collection stuList to Array like this
Object[] stuArr = stuList.toArray();           // <----- toArray() function will convert collection to array
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.