우리는 특정 해에 관한 몇 가지 데이터를 보유하고있는 객체 A가 있다고 가정합시다. 이 객체는 전년도에 속한 데이터를 보유하는 동일한 클래스의 다른 객체에 대한 참조를가집니다.자기 참조로 객체를 반복하십시오.
Java 스트림에서 이러한 모든 개체 (현재 연도, previos, previos 작년 ...)의 목록을 생성 할 수 있습니까?
안부
우리는 특정 해에 관한 몇 가지 데이터를 보유하고있는 객체 A가 있다고 가정합시다. 이 객체는 전년도에 속한 데이터를 보유하는 동일한 클래스의 다른 객체에 대한 참조를가집니다.자기 참조로 객체를 반복하십시오.
Java 스트림에서 이러한 모든 개체 (현재 연도, previos, previos 작년 ...)의 목록을 생성 할 수 있습니까?
안부
때문에 당신은 당신의 자신의 Iterator<T>
를 구현하고 Stream<T>
같은으로 변환 할 수 있습니다 사용법은 다음과 같을 수 있습니다
private static <T> Stream<T> iterate(T root, UnaryOperator<T> generator, Predicate<T> stop) {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(new Iterator<T>() {
private T t = root;
@Override
public boolean hasNext() {
return stop.test(t);
}
@Override
public T next() {
T result = t;
t = generator.apply(t);
return result;
}
}, Spliterator.IMMUTABLE | Spliterator.ORDERED), false);
}
: 간단하게
Stream<A> s = iterate(root, t -> t.next, Objects::nonNull);
Btw와 비슷하다. 3-arg'iterate' 메소드는 Java 9에도 추가되었습니다. [문서 참조] (http://download.java.net/java/jdk9/docs/api/java/util/stream/Stream.html#iterate-T -Java.util.function.Predicate-java.util.function.UnaryOperator-). –
@ TagirValeev이 방법을 알지 못했습니다. 참조 주셔서 감사합니다. – Flown
이 절대적으로 스트림 API를 사용하여 수행해야하는 경우, 여기에 그 일의 잠재적 인 방법입니다. 마지막 개체 A
은 전년도에 대한 참조에서 null
을 가지므로 그 술어 - elem -> elem != null
을 가정합니다. null이 아니거나 어떤 종류의 A.NULL
객체가 있으면 간단히 그에 따라 술어를 수정하십시오. takeWhile
작업이 JDK 9에서 사용할 수
import java.util.List;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
public class Test {
public static void main(String[] args) {
A a = new A(2016);
a.prev = new A(2015);
a.prev.prev = new A(2014);
a.prev.prev.prev = new A(2013);
// .. etc
List<A> list = takeWhile(Stream.iterate(a, elem -> elem.prev),
elem -> elem != null)
.collect(Collectors.toList());
// this prints - 2016, 2015, 2014, 2013
System.out.println(list);
}
/**
* This has been taken from this SO answer:
* http://stackoverflow.com/questions/20746429/limit-a-stream-by-a-predicate
*/
static <T> Spliterator<T> takeWhile(
Spliterator<T> splitr, Predicate<? super T> predicate) {
return new Spliterators.AbstractSpliterator<T>(splitr.estimateSize(), 0) {
boolean stillGoing = true;
@Override public boolean tryAdvance(Consumer<? super T> consumer) {
if (stillGoing) {
boolean hadNext = splitr.tryAdvance(elem -> {
if (predicate.test(elem)) {
consumer.accept(elem);
} else {
stillGoing = false;
}
});
return hadNext && stillGoing;
}
return false;
}
};
}
static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<? super T> predicate) {
return StreamSupport.stream(takeWhile(stream.spliterator(), predicate), false);
}
static class A {
A prev;
int year;
// some other data
public A(int year) {
this.year = year;
}
@Override
public String toString() {
return year + "";
}
}
}
전체 tryAdvance 구현은'return stillGoing && splitr.tryAdvance (consumer-accept (elem));}) && stillGoing;' – Holger
예 . 먼저 공통 Java 스타일로 시도한 다음 알고리즘을'Stream' API로 변환하십시오. – Flown