2009-04-20 2 views
7

내가 배열을 받아 그것을 사용하여 각 요소를 처리하는 방법에있어 가정 자바의 for-each loop에 내장 된이 같은 :모든 for-each 루프와 함께 작동하는 Java에서 사용할 수있는 매개 변수가 있습니까?

public static void myFun(SomeClass[] arr) { 
    for (SomeClass sc : arr) { 
     // Stuff is processed here 
    } 
} 

이 잘 작동하지만 지금은 통과 할 수 있도록하려면 대신 같은 방법으로 List<SomeClass>을 입력하십시오. Collection.toArray(T [])을 사용하겠습니까? for-each 구문에 사용할 수있는 모든 유형을 허용하는 myFun()에 사용할 수있는 매개 변수가 있습니까?

명확하게하려면 : 원시 배열이나 컬렉션이 될 수있는 반복 가능한 객체를 허용하는 메서드 서명이 필요합니다. 하나는 다른 것을 래핑하는 방법과 함께 두 가지 방법을 매우 쉽게 작성할 수 있지만, 더 좋은 방법이 있다면 궁금 할 것입니다.

+0

배열은 Iterable을 구현하지 않으므로 불행히도 대답은 '아니오'입니다. –

답변

9

내가 Iterable, Collection 또는 매개 변수 유형으로 List을 사용하는 것이 좋습니다 것입니다.

IMO, 컬렉션을 참조하는 것이 좋습니다. 어레이가 발생하면 Arrays.asList 변환이 제대로 수행됩니다. Arrays.asList을 사용하면 가져 오기 및 배열을 다시 배열로 보낼 수 있지만 배열 길이를 변경하는 "구조적"수정은 분명하지 않습니다.

myFun(Arrays.asList(arr)); 

극단적 인/일반적인 경우에는 와일드 카드를 사용해야 할 수도 있습니다.

public static void myFun(Iterable<? extends SomeClass> somethings) { 
    for (SomeClass something : somethings) { 
     // something is processed here 
    } 
} 

그것은 그 Collections.toArrayArrays.asList 작업을 약간 다르게 주목할 만하다. asList은 원래 배열이 콜렉션을 백업하도록 유지하므로 콜렉션의 변경 사항이 배열에 반영됩니다. Collections.toArray은 콜렉션 데이터의 (얕은) 사본을 작성합니다. 배열을 반환하는 경우 복사본을 만드는 것이 종종 원하는 것입니다. 비대칭 적으로, 인수로 전달하는 경우 일반적으로 (필드로 저장하지 않는 한) 복사하지 않습니다.

+0

동의합니다; 이런 경우 Iterable을 사용하기 때문에 구현 자에게 최소한의 부담이됩니다. 그리고 Object []를 직접 사용할 수는 없지만 Arrays.asList()를 사용하여 이것을 연결하는 것은 쉽지 않습니다. – erickson

+0

예. OTOH에서는 구현이 반복하기 전에 컬렉션 크기를 원할 수도 있으며 대부분의 코드는 여전히 Collection을 사용합니다. –

+0

asList() 또는 toArray()를 피할 방법이없는 것 같으면이 논리에 가장 동의합니다. Object [] 대신 Iterable을 사용하는 것이 합리적입니다. –

5

Iterable을 사용하십시오. 그것이 바로 그 때문입니다.

앞서 말씀 드린대로 Iterable은 배열을 처리하지 않습니다.

서로 포장하는 여러 가지 방법을 사용하고 싶지는 않습니다. 그건 Arrays.asListCollection.toArray을 배제합니다.

귀하의 질문에 대한 답변은 아니오입니다. 따라서 방법은 없습니다. 그러나 을 사용하면 Lists을 사용하는 이유는 무엇입니까?

여기에 Iterable과 같이 표시됩니다. 저는 이전에 Iterable을 구현 한 클래스를 가지고 있었지만 콜렉션이 아니기 때문에 Collection보다 더 좋았습니다. 이렇게하면 필요에 따라 lazily 값을 쉽게 검색 할 수 있으며 foreach 루프를 사용할 수 있습니다.

+2

Iterable을 매개 변수로 사용하면 기본 배열을 전달할 때 컴파일 오류가 발생합니다. –

+0

우, 그런 생각을하지 못했습니다. 내가 조금 생각해 보자. –

+0

Is Object [] Iterable ?? –

-3
public static void myFun(Collection<MyClass> collection) { 
    for (MyClass mc : collection) { 
     // Stuff is processed here 
    } 
} 
+0

MyCalss. –

+0

이것은 배열을 전달할 때 작동하지 않습니다. –

3

당신은 자바 어레이의 Iterable을 구현하지 않습니다하지

public static int sum(Iterable<Integer> elements) { 
    int s = 0; 

    for (int i : elements) { 
     s += i; 
    } 

    return s; 
} 

public static void main(String[] args) { 
    L1: System.out.println(sum(1,2,3)); 
    L2: System.out.println(sum(Arrays.asList(1,2,3))); 
    L3: System.out.println(sum(new int[] { 1,2,3 })); 
} 

를이 (L1과 L3)에 두 개의 컴파일 타임 오류가 발생;

당신이 시도 할 수있다 : 그래서 당신은

해결 과정, 적어도 하나의 방법은 (배열에 /) 일부 변환을 수행해야하는 반복 가능 (컬렉션) 및/또는 배열을 받아 들일 당신의 방법을 설계해야

public class ArrayIterator<T> implements Iterator<T> { 

    private final T[] array; 
    private int i; 

    public ArrayIterator(T[] anArray) { 
     array = anArray; 
     i = 0; 
    } 

    public boolean hasNext() { 
     return i < array.length; 
    } 

    public T next() { 
     return array[i++]; 
    } 

    public void remove() { 
     throw new UnsupportedOperationException(); 
    } 
} 

private static int sum(final Integer ... elements) { 
    return sum(new Iterable<Integer>() { 

     public Iterator<Integer> iterator() { 
      return new ArrayIterator<Integer>(elements); 
     } 
    }); 
} 

프리미티브 배열을 다룰 때만주의해야합니다. 당신은 단지 참조 객체를 (귀하의 경우) ArrayIterator + 익명 클래스는 멋진

그것이

0

당신이 당신의 메서드 호출과에 <? extends Subtype>을 사용할 수있는 자바 1.5 이상에서 자바 제네릭의 작은 알고 기능이있어 도움이되기를 바랍니다 사용할 때 생성자. <? extends Object>을 사용할 수 있습니다. 그런 다음이 객체를 다루는 항목은 Object의 메서드에만 액세스 할 수 있습니다. 당신이 정말 할 수 있습니다하면이 같은 뭔가 더있다 :

List<? extends MyCrustaceans> seaLife = new ArrayList<? extends MyCrustaceans>(); 
MyShrimp s = new MyShrimp("bubba"); 
seaLife.add(s); 
DoStuff(seaLife); 

... 

public static void DoStuff(List<? extends MyCrustaceans> seaLife) 
{ 
    for (MyCrustaceans c : seaLife) { 
     System.out.println(c); 
    } 
} 

당신이 (MyCrustaceans 같은) 기본 클래스가있는 경우 경우에 따라서, 당신은, DoStuff에 그 기본 클래스의 방법을 사용 (또는 Object 클래스의 수 있습니다 매개 변수는 <? extends Object>입니다. <? super MyType>과 유사한 기능이 있는데, 하위 유형 대신 지정된 유형의 상위 유형 인 매개 변수를 허용합니다. 이런 식으로 "확장"과 "확장"을 사용할 수있는 것에는 몇 가지 제한이 있습니다. 여기에 good place to find more info이 있습니다.

1

짧은 대답 : 아니요, 반복적으로 배열과 배열을 모두 허용하는 단일 메서드 서명이 없습니다. 분명히 Object을 수락 할 수 있지만 해킹 일 수도 있습니다.

긴 틱 답변 : 비록

public static void myFun(SomeClass[] array) { 
    for (SomeClass sc : array) { 
     doTheProcessing(sc); 
    } 
} 

public static void myFun(Iterable<? extends SomeClass> iterable) { 
    for (SomeClass sc : iterable) { 
     doTheProcessing(sc); 
    } 
} 

: 강화 for -loop 효과적으로 (한 번 Iterable에 대한 배열에 대해 한 번)를 두 번 정의되어 있기 때문에, 당신은뿐만 아니라 오버로드 된 두 가지 방법을 제공해야합니다 두 메서드의 소스가 완전히 똑같아 보이면 두 번 정의해야합니다 (단, @dfa를 설명한대로 자신의 Iterable에 배열을 래핑하지 않는 한).

+0

"명확하게하려면 : 반복 가능한 객체를 허용하는 메소드 서명이 필요합니다. 기본 배열 또는 Collection 일 수 있습니다. 다른 메소드를 래핑하는 방법과, 그러나 더 좋은 방법이 있다면 나는 단지 호기심이 듭니다. " –

+0

좋아, 그럼 난 충분히 질문을 읽지 않았다. 나는 이것이 더 나은 것이기를 바랍니다. –

+1

그래, 정말로 다른 대답은 없습니다. 모든 "답변"은 단지 해결 방법이나 조언 일뿐입니다. –

관련 문제