Java 열거를 스트림으로 어떻게 전환합니까?
나에게 Enumeration<String>
. 나는 자바 8로 유유히 그 열거 작업 할 Stream
, 같은 것들을 호출 filter
, map
그리고 flatMap
그 위에.
이 라이브러리가있는 기존 라이브러리가 있습니까? 나는 이미 Guava와 Apache Commons를 참조하고 있으므로 둘 중 하나가 이상적인 솔루션을 가지고 있다면.
또는, 설정하는 가장 / 가장 쉬운 방법은 무엇 Enumeration
에이 Stream
모든 것을 게으른 성격을 유지하면서는?
이 답변은 이미 다음을 만드는 솔루션을 제공 Stream
합니다 Enumeration
.
public static <T> Stream<T> enumerationAsStream(Enumeration<T> e) { return StreamSupport.stream( Spliterators.spliteratorUnknownSize( new Iterator<T>() { public T next() { return e.nextElement(); } public boolean hasNext() { return e.hasMoreElements(); } }, Spliterator.ORDERED), false); }
터미널 작업이 시작되기 전에는 어떤 항목도 처리하지 않고 터미널 작업이 단락되면 필요한만큼만 항목을 반복 하므로 결과 Stream
는 다른 Stream
모든 항목 만큼 지연 된다는 점을 강조해야합니다 .
그래도 개선의 여지가 있습니다. forEachRemaining
모든 요소를 처리하는 간단한 방법이있을 때 항상 메서드를 추가합니다 . 상기 메서드는 Stream
대부분의 비 단락 작업 에 대한 구현에 의해 호출됩니다 .
public static <T> Stream<T> enumerationAsStream(Enumeration<T> e) {
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
new Iterator<T>() {
public T next() {
return e.nextElement();
}
public boolean hasNext() {
return e.hasMoreElements();
}
public void forEachRemaining(Consumer<? super T> action) {
while(e.hasMoreElements()) action.accept(e.nextElement());
}
},
Spliterator.ORDERED), false);
}
그러나 위의 코드는 " Iterator
너무 친숙하기 때문에 사용 하는"반 패턴의 희생양입니다 . 생성 된 파일 Iterator
은 새 Spliterator
인터페이스 의 구현으로 래핑되며 Spliterator
직접 구현하는 것보다 이점을 제공하지 않습니다 .
public static <T> Stream<T> enumerationAsStream(Enumeration<T> e) {
return StreamSupport.stream(
new Spliterators.AbstractSpliterator<T>(Long.MAX_VALUE, Spliterator.ORDERED) {
public boolean tryAdvance(Consumer<? super T> action) {
if(e.hasMoreElements()) {
action.accept(e.nextElement());
return true;
}
return false;
}
public void forEachRemaining(Consumer<? super T> action) {
while(e.hasMoreElements()) action.accept(e.nextElement());
}
}, false);
}
소스 코드 수준에서이 구현은 Iterator
기반 만큼 간단 하지만 a Spliterator
에서 Iterator
. 독자가 새 API에 대해 배우기 만하면됩니다.
바닐라 자바를 사용하지 않는 이유 :
Collections.list(enumeration).stream()...
그러나 @MicahZoltu에서 언급했듯이 Collections.list
열거 형의 요소를 복사하기 위해 먼저 열거 형을 반복 하므로 열거 형의 항목 수를 고려해야 합니다 ArrayList
. 거기에서 일반적인 stream
방법을 사용할 수 있습니다. 이것은 많은 컬렉션 스트림 작업에 일반적이지만 열거가 너무 크면 (무한대처럼) 열거를 목록으로 변환해야하므로 여기에 설명 된 다른 접근 방식을 대신 사용해야하기 때문에 문제가 발생할 수 있습니다.
In Java 9 it is possible to convert an Enumeration
to a Stream
with a one-liner:
Enumeration<String> en = ... ;
Stream<String> str = StreamSupport.stream(
Spliterators.spliteratorUnknownSize(en.asIterator(), Spliterator.ORDERED),
false
);
(Well, it's a rather long line.)
If you're not on Java 9, you can convert the Enumeration
into an Iterator
manually using the technique given in Holger's answer.
According to Guava docs, you could use the Iterators.forEnumeration()
method:
Enumeration<Something> enumeration = ...;
Iterator<SomeThing> iterator = Iterators.forEnumeration(enumeration);
And in this question, it is explained how to get a stream from an iterator:
Stream<Something> stream = StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
iterator, Spliterator.ORDERED),
false);
In my StreamEx library there's simple method StreamEx.of(Enumeration)
which does the job:
Stream<String> stream = StreamEx.of(enumeration);
Note that it not just a shortcut to the @Holger solution, but implemented in different manner. In particular, it has significantly better parallel execution characteristics compared to solutions involving Spliterators.spliteratorUnknownSize()
.
ReferenceURL : https://stackoverflow.com/questions/33242577/how-do-i-turn-a-java-enumeration-into-a-stream
'programing' 카테고리의 다른 글
Android에서 카드 뷰 주변의 그림자를 비활성화하는 방법 (0) | 2021.01.16 |
---|---|
SQL 언어가 구성되지 않음 (Phpstorm) (0) | 2021.01.16 |
Jmap은 덤프를 만들기 위해 연결할 수 없습니다. (0) | 2021.01.16 |
Rails에서 jquery-ui 자동 완성을 설정하는 방법 (0) | 2021.01.16 |
IntegrityError 중복 키 값이 고유 제약 조건을 위반 함-django / postgres (0) | 2021.01.16 |