2016-08-26 5 views
0

우리는 특정 해에 관한 몇 가지 데이터를 보유하고있는 객체 A가 있다고 가정합시다. 이 객체는 전년도에 속한 데이터를 보유하는 동일한 클래스의 다른 객체에 대한 참조를가집니다.자기 참조로 객체를 반복하십시오.

Java 스트림에서 이러한 모든 개체 (현재 연도, previos, previos 작년 ...)의 목록을 생성 할 수 있습니까?

안부

+1

예 . 먼저 공통 Java 스타일로 시도한 다음 알고리즘을'Stream' API로 변환하십시오. – Flown

답변

2

때문에 당신은 당신의 자신의 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); 
+2

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-). –

+0

@ TagirValeev이 방법을 알지 못했습니다. 참조 주셔서 감사합니다. – Flown

1

이 절대적으로 스트림 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 + ""; 
     } 
    } 
} 
+1

전체 tryAdvance 구현은'return stillGoing && splitr.tryAdvance (consumer-accept (elem));}) && stillGoing;' – Holger

관련 문제