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


150

예를 들어 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)

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



LinkedList에 추가 한 다음 해당 Set의 반복자를 반환하십시오.

답변:


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

10
두 주 : 1) 그는이 int아닌 Integer2) List이미 Iterable세 번째 줄은 무의미하므로.
maksimov

1
그는 왜 세 번째 줄이 있는지 Iterable이 필요합니다.
fmucar

5
두 번째와 세 번째 줄은 내가 말할 옵션입니다 :)
fmucar

1
이것은 숙제의 일부가 아니며 배열 또는 목록의 내용을 처리하는 디버깅 함수의 코드 복제를 피하려고했습니다 ... 둘러 보면서 실제로 Arrays.asList (..);를 찾았습니다. Eclipse는 내가 원하는 것을하지 않을 것이라고 생각하는 것 같습니다 (예 : List <Integer>가 아닌 List <int []>로 Arrays.asList (foo)의 결과를 유추합니다). 질문 ... (
제한

1
일반적으로 할 수있는 많은 방법을 생각할 수는 있지만 BEST가 무엇인지 궁금합니다. 예를 들어 루프가 더 느리게 흐려질 수 있습니다 ... {음, 아무것도 생각할 수 없습니다! : )}) 또한 왜, 내 질문은 왜가 아니라 어떻게, 어떤 유형의 컨테이너가 가장 좋은지에 대한 토론을 보려면 stackoverflow.com/questions/1160081/… 도 확인하십시오 (어떻게 ArrayList? Generics를 사용하는 래퍼 .. 아마 크기에 따라 다릅니다 ...)
ntg

44

내 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.");
            }
        };
    }
};

9
remove ()는 UnsupportedOperationException을 발생시키는 기본 메소드이므로 java 8에서는 필요하지 않습니다. 더 나은 설명 메시지를 제공하려는 경우에만.
Alex

+1 Iterator<Character>에서 를 만드는 비슷한 작업을 수행 합니다 String. 자신을 구현하는 것은 Iterator(구아바의를 통해 기본 유형에 개체 형식으로 변환하는 모든 값을 반복 불필요하게 피할 수있는 유일한 방법처럼 보인다 Ints.asList()단지를 얻을 수 있도록, 예를 들면) Iterator에서 List생성 된 그.
spaaarky21

2
네가 맞아 Alex. 기본 메소드가 Java 8에 추가되었습니다. 2013 년에이 고대 코드를 여기에 추가했습니다.
Joerg Ruethschilling

29

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

20

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 요소 배열의 배열을 생성 한 것입니다.


참고 사항 : 링크가 더 이상 작동하지 않습니다. Github 링크 : github.com/google/guava/blob/master/guava/src/com/google/common/…
Orangle

감사합니다 @Passi, 고정 (더 이상 Google 문서를 javadoc에 연결하는 방법을 찾을 수 없으므로 제공 한 소스에 연결되었습니다).
BeeOnRope

8

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

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

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


7

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

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 ++ 프로그램에서 사용하는 메모리와 아무런 차이가 없습니다).


3

CactoosIterableOf 에서 사용할 수 있습니다 :

Iterable<String> names = new IterableOf<>(
  "Scott Fitzgerald", "Fyodor Dostoyevsky"
);

그런 다음 다음을 사용하여 목록으로 바꿀 수 있습니다 ListOf.

List<String> names = new ListOf<>(
  new IterableOf<>(
    "Scott Fitzgerald", "Fyodor Dostoyevsky"
  )
);

아니면 간단히 :

List<String> names = new ListOf<>(
  "Scott Fitzgerald", "Fyodor Dostoyevsky"
);

1

비슷한 답변이 이미 게시되었지만 새로운 PrimitiveIterator.OfInt를 사용해야하는 이유는 분명하지 않습니다. 좋은 해결책은 프리미티브 int 유형에 특화된 Java 8 PrimitiveIterator를 사용하는 것입니다 (추가적인 boxing / unboxing 페널티를 피함).

    int[] arr = {1,2,3};
    // If you use Iterator<Integer> here as type then you can't get the actual benefit of being able to use nextInt() later
    PrimitiveIterator.OfInt iterator = Arrays.stream(arr).iterator();
    while (iterator.hasNext()) {
        System.out.println(iterator.nextInt());
        // Use nextInt() instead of next() here to avoid extra boxing penalty
    }

참조 : https://doc.bccnsoft.com/docs/jdk8u12-docs/api/java/util/PrimitiveIterator.OfInt.html


-2

java8에서는 IntSteam 스트림을 정수 스트림으로 박스로 묶을 수 있습니다.

public static Iterable<Integer> toIterable(int[] ints) {
    return IntStream.of(ints).boxed().collect(Collectors.toList());
}

어레이의 크기에 따라 성능이 중요하다고 생각합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.