[java] Java 배열을 반복 가능으로 변환

예를 들어 int, int [] foo와 같은 프리미티브 배열이 있습니다. 작은 크기 일 수도 있고 아닐 수도 있습니다.

int foo[] = {1,2,3,4,5,6,7,8,9,0};

Iterable<Integer>그것을 만드는 가장 좋은 방법은 무엇입니까 ?

Iterable<Integer> fooBar = convert(foo);

노트:

루프를 사용하여 대답하지 마십시오 (컴파일러가 어떻게 똑똑한지를 설명 할 수 없다면?)

또한

int a[] = {1,2,3};
List<Integer> l = Arrays.asList(a);

컴파일조차하지 않습니다

Type mismatch: cannot convert from List<int[]> to List<Integer>

또한 왜 배열이 Iterable에 할당 될 수 없는지 확인하십시오
.
대답하기 전에.

또한 일부 라이브러리 (예 : 구아바)를 사용하는 경우 이것이 왜 최고인지 설명하십시오. (Google의 답변이 완전하지 않기 때문에 : P)

마지막으로, 그것에 관한 숙제가있는 것 같으므로 숙제 코드를 게시하지 마십시오.



답변

Integer foo[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };

List<Integer> list = Arrays.asList(foo);
// or
Iterable<Integer> iterable = Arrays.asList(foo);

이것이 작동 하려면 Integer배열 (배열이 아닌) 을 사용해야합니다 int.

프리미티브의 경우 구아바를 사용할 수 있습니다.

Iterable<Integer> fooBar = Ints.asList(foo);
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>15.0</version>
    <type>jar</type>
</dependency>

Java8의 경우 : (Jin Kwon의 답변에서)

final int[] arr = {1, 2, 3};
final PrimitiveIterator.OfInt i1 = Arrays.stream(arr).iterator();
final PrimitiveIterator.OfInt i2 = IntStream.of(arr).iterator();
final Iterator<Integer> i3 = IntStream.of(arr).boxed().iterator();


답변

내 2 센트 만 :

final int a[] = {1,2,3};

java.lang.Iterable<Integer> aIterable=new Iterable<Integer>() {

    public Iterator<Integer> iterator() {
       return new Iterator<Integer>() {
            private int pos=0;

            public boolean hasNext() {
               return a.length>pos;
            }

            public Integer next() {
               return a[pos++];
            }

            public void remove() {
                throw new UnsupportedOperationException("Cannot remove an element of an array.");
            }
        };
    }
};


답변

Java 8을 사용하면이 작업을 수행 할 수 있습니다.

final int[] arr = {1, 2, 3};
final PrimitiveIterator.OfInt i1 = Arrays.stream(arr).iterator();
final PrimitiveIterator.OfInt i2 = IntStream.of(arr).iterator();
final Iterator<Integer> i3 = IntStream.of(arr).boxed().iterator();


답변

Guava는 원하는 어댑터를 Int.asList () 로 제공합니다 . 연관된 클래스의 각 기본 유형 (예 : Booleansfor boolean등)에 해당합니다.

int foo[] = {1,2,3,4,5,6,7,8,9,0};
Iterable<Integer> fooBar = Ints.asList(foo);
for(Integer i : fooBar) {
    System.out.println(i);
}

사용 위의 제안은 Arrays.asList하지 작업, 그들이 컴파일 할 경우에도 당신은 얻을 것이다 때문 Iterator<int[]>이 아니라 Iterator<Integer>. 결과는 배열이 지원하는 목록을 생성하는 대신 배열을 포함하는 1 요소 배열의 배열을 생성 한 것입니다.


답변

나는 같은 문제가 있었고 다음과 같이 해결했다.

final YourType[] yourArray = ...;
return new Iterable<YourType>() {
  public Iterator<YourType> iterator() {
     return Iterators.forArray(yourArray);   // Iterators is a Google guava utility
  }
}

이터레이터 자체는 게으르지 UnmodifiableIterator만 정확히 내가 필요한 것입니다.


답변

Java 8 이상에서는 Iterable기능 인터페이스가를 반환합니다 Iterator. 그래서 당신은 이것을 할 수 있습니다.

int[] array = {1, 2, 3};
Iterable<Integer> iterable = () -> Arrays.stream(array).iterator();
for (int i : iterable)
    System.out.println(i);

->

1
2
3


답변

우선, 필자는 기본 Arrays.asList(T...)이 아닌 데이터 유형이있는 래퍼 유형 또는 배열에 가장 적합한 솔루션 이라는 것에 동의 할 수 있습니다 . 이 메소드는 기본적으로 주어진 배열 참조를 필드로 저장하고 필요한 메소드를 대체하여 목록을 시뮬레이트하는 클래스 AbstractList에서 간단한 개인 정적 구현 의 생성자를 호출 Arrays합니다.

배열의 기본 유형 또는 래퍼 유형 중에서 선택할 수 있다면 그러한 상황에 래퍼 유형을 사용하지만 물론 항상 유용하거나 필요한 것은 아닙니다. 당신이 할 수있는 두 가지 가능성이있을 것입니다 :

1) 각 원시 데이터 유형 배열에 대해 정적 메소드를 사용하여 클래스를 만들 수 있습니다 ( WrapperType boolean, byte, short, int, long, char, float, double반환) .이 메소드는 익명 클래스를 사용합니다 (Iterable<>IteratorIterable메소드 int[]를 구현하기 위해 포함 메소드의 인수 (예 🙂 를 필드로 포함 할 수 있습니다.

->이 방법은 성능이 뛰어나고 메모리를 절약합니다 (새로 생성 된 메소드의 메모리는 제외하고 Arrays.asList()동일한 방식으로 메모리를 사용하지만 )

2) 배열에는 메소드가 없으므로 (측면에서 읽을) 당신은 링크) 그들은 Iterator인스턴스를 제공 할 수 없습니다 . 새 클래스를 작성하기에 너무 게으른 Iterable경우 인스턴스화 Iterable또는 하위 유형 외에 다른 방법이 없기 때문에 구현하는 기존 클래스의 인스턴스를 사용해야합니다 .
기존 Collection 파생물 구현을 만드는 유일한 방법Iterable루프를 사용하거나 (위에서 설명한 것처럼 익명 클래스를 사용하는 것을 제외하고) Iterable생성자 Object[]가 기본 유형 배열을 허용하지만 (기본 유형 요소가있는 배열을 허용하지 않기 때문에 ) Java API를 구현 하는 구현 클래스 를 인스턴스화하는 것입니다. 그런 클래스는 없습니다.

루프의 이유는 쉽게 설명 할 수 있습니다.
각 컬렉션마다 객체가 필요하고 기본 데이터 유형은 객체가 아닙니다. 객체는 기본 유형보다 훨씬 크기 때문에 기본 유형 배열의 각 요소에 대해 생성해야하는 추가 데이터가 필요합니다. 즉 Arrays.asList(T...), 기존 컬렉션을 사용 하거나 사용하는 세 가지 방법 중 두 가지 방법으로 객체를 집계해야하는 경우 각 기본 값에 대해 생성해야합니다.int[]래퍼 객체를 배열합니다. 세 번째 방법은 배열을 그대로 사용하고 익명의 클래스에서 사용하는 것입니다. 성능이 빠르기 때문에 선호한다고 생각합니다. 배열을 사용하려는 메소드에 as 인수를

사용하는 세 번째 전략 이 있으며 인수가 어떤 유형인지 파악하기 위해 유형 검사가 필요하지만 일반적으로 필요에 따라 권장하지는 않습니다. Object가 항상 필요한 유형은 아니며 특정 경우 별도의 코드가 필요하다는 것을 고려하십시오. ObjectIterable

결론적으로, 기본 유형을 일반 유형으로 사용하여 단순 코드를 사용하여 많은 코드를 절약 할 수없는 Java의 문제가있는 일반 유형 시스템의 결함입니다 Arrays.asList(T...). 따라서 각 기본 유형 배열에 대해 프로그래밍해야합니다. 이러한 메소드 (기본적으로 사용되는 유형 인수마다 별도의 메소드를 생성하는 C ++ 프로그램에서 사용하는 메모리와 아무런 차이가 없습니다).