#98 Write Spliterator for flatIf, deepFlatIf, treeFlatIf

오픈
ranides3 년 전을 오픈 · 8개의 코멘트
ranides 코멘트됨, 3 년 전

We want map/flat iterator which simply consumes Iterator<T> and transforms next element on the fly, if necessary. Don't use intermediate singleton iterators.

That means, we should use simple stack. Method next will just take iterator from top of the stack and:

  • if iterator is empty, will pop it and try next value from the stack
  • if iterator.next is non-transformable, returns item
  • if item is transformable, it transforms, pushes generated iterator on stack and executes "next" again

Such strategy allows us to implement two things:

  • flatten without intermediate singleton iterators
  • flatten recursively, it is deep flatten

In fact, strategy described above is "recursive". If we want to have shallow flattening, we should check transformable only if the stack.size = 1

We want map/flat iterator which simply consumes `Iterator<T>` and transforms next element on the fly, if necessary. Don't use intermediate singleton iterators. That means, we should use simple stack. Method `next` will just take iterator from top of the stack and: - if iterator is empty, will pop it and try next value from the stack - if iterator.next is non-transformable, returns item - if item is transformable, it transforms, pushes generated iterator on stack and executes "next" again Such strategy allows us to implement two things: - flatten without intermediate singleton iterators - flatten recursively, it is deep flatten In fact, strategy described above is "recursive". If we want to have shallow flattening, we should check transformable only if the stack.size = 1
ranides 코멘트됨, 3 년 전
소유자

Again, this way will give us:

  • flatIf
  • flatWhile
Again, this way will give us: - `flatIf` - `flatWhile`
ranides 코멘트됨, 3 년 전
소유자

The question is, what to do with CQuery.flatIf/CQuery.flatWhile when we want to use Stream instead of Iterator.

If using Stream.flatMap we need to use singletonStream. What's more, we need to wrap generated flattened stream by flatMap again.

The question is, what to do with CQuery.flatIf/CQuery.flatWhile when we want to use Stream instead of Iterator. If using Stream.flatMap we need to use singletonStream. What's more, we need to wrap generated flattened stream by flatMap again.
ranides 코멘트됨, 3 년 전
소유자

There is reasonable flatMap implementation:

https://stackoverflow.com/questions/32749148/in-java-how-do-i-efficiently-and-elegantly-stream-a-tree-nodes-descendants/32767282#32767282

Probably we can write reasonable flatMapIf implementation using example above.

What's more, it is good workaround for JDK bug, much better than returning to iterator all the time.

There is reasonable flatMap implementation: https://stackoverflow.com/questions/32749148/in-java-how-do-i-efficiently-and-elegantly-stream-a-tree-nodes-descendants/32767282#32767282 Probably we can write reasonable flatMapIf implementation using example above. What's more, it is good workaround for JDK bug, much better than returning to iterator all the time.
ranides 코멘트됨, 3 년 전
소유자

We can write addintional, better IteratorUtils.flat too if we use strategy described above. It is simply unconditional, shallow flat.

Current version: flat(Iterator<Iterator<T>> input)

Additional possible version: flat(Iterator<T> input, Function<T, Iterator<T>> splitter)

We can write addintional, better IteratorUtils.flat too if we use strategy described above. It is simply unconditional, shallow flat. Current version: `flat(Iterator<Iterator<T>> input)` Additional possible version: `flat(Iterator<T> input, Function<T, Iterator<T>> splitter)`
ranides 코멘트됨, 3 년 전
소유자

Very important: we need to support preserving splitted value and returning it too. It means: item will be transformed to {data, splitted data...} instead of {splitted data...} alone.

It is possibly trivial: one flag which decides to return item first, even if it is transformable, put into last and our next method should split last item instead of the item retrieved from iterator-stack (retrieved item must be returned always if flag is enabled)

We need that if we want to implement #50 correctly in easy way (we don't want to loose interfaces which implements other interfaces, we want to return all of them, both parent and children).

At the level of non-recursive stream it is something like:

stream.flatMap(v -> Stream.of(v).concat(splitme(v)) )

instead of

stream.flatMap(v -> splitme(v) )

or more precisely

stream.flatMap(v -> condition ? Stream.of(v).concat(splitme(v)) : Stream.of(v) )

instead of

stream.flatMap(v -> condition ? splitme(v) : Stream.of(v) )

recursive version (even more complicated):

stream.flatMap(v -> condition ? Stream.of(v).concat( flatIf(condition, splitme(v)) ) : Stream.of(v))

instead of

stream.flatMap(v -> condition ? flatIf(condition, splitme(v)) : Stream.of(v) )
Very important: we need to support preserving splitted value and returning it too. It means: `item` will be transformed to `{data, splitted data...}` instead of `{splitted data...}` alone. It is possibly trivial: one flag which decides to return item first, even if it is transformable, put into `last` and our `next` method should split `last` item instead of the item retrieved from iterator-stack (retrieved item must be returned always if flag is enabled) We need that if we want to implement #50 correctly in easy way (we don't want to loose interfaces which implements other interfaces, we want to return all of them, both parent and children). At the level of non-recursive stream it is something like: ``` stream.flatMap(v -> Stream.of(v).concat(splitme(v)) ) ``` instead of ``` stream.flatMap(v -> splitme(v) ) ``` or more precisely ``` stream.flatMap(v -> condition ? Stream.of(v).concat(splitme(v)) : Stream.of(v) ) ``` instead of ``` stream.flatMap(v -> condition ? splitme(v) : Stream.of(v) ) ``` recursive version (even more complicated): ``` stream.flatMap(v -> condition ? Stream.of(v).concat( flatIf(condition, splitme(v)) ) : Stream.of(v)) ``` instead of ``` stream.flatMap(v -> condition ? flatIf(condition, splitme(v)) : Stream.of(v) ) ```
ranides 코멘트됨, 3 년 전
소유자

done: iterator version

todo: stream/spliterator version

todo: CQuery#deepFlatIf and CQuery#treeFlatIf

done: iterator version todo: stream/spliterator version todo: `CQuery#deepFlatIf` and `CQuery#treeFlatIf`
ranides 코멘트됨, 3 년 전
소유자

todo: stream/spliterator version. Now we just delegate all CQuery flat to IteratorUtils. That means we are not parallelizable.

todo: stream/spliterator version. Now we just delegate all CQuery `flat` to IteratorUtils. That means we are not parallelizable.
ranides 커밋 3 년 전에서 이 이슈 언급
ranides 코멘트됨, 3 년 전
소유자

todo: we should write optimized versions for CQuery#each too

todo: we should write optimized versions for `CQuery#each` too
로그인하여 이 대화에 참여
마일스톤 없음
담당자 없음
참여자 1명
로딩중...
취소
저장
아직 콘텐츠가 없습니다.