001 /*
002 * Java Genetic Algorithm Library (jenetics-5.1.0).
003 * Copyright (c) 2007-2019 Franz Wilhelmstötter
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 *
017 * Author:
018 * Franz Wilhelmstötter (franz.wilhelmstoetter@gmail.com)
019 */
020 package io.jenetics.ext.internal;
021
022 import java.util.Collection;
023 import java.util.Deque;
024 import java.util.LinkedList;
025 import java.util.List;
026 import java.util.Objects;
027 import java.util.Spliterator;
028 import java.util.function.Consumer;
029 import java.util.stream.Collectors;
030
031 /**
032 * This {@code Spliterator} takes a list of other spliterators which are
033 * concatenated and a limiting predicate.
034 *
035 * @author <a href="mailto:franz.wilhelmstoetter@gmail.com">Franz Wilhelmstötter</a>
036 * @version 4.1
037 * @since 4.1
038 */
039 public class ConcatSpliterator<T> implements Spliterator<T> {
040
041 private final Deque<Spliterator<T>> _spliterators;
042
043 /**
044 * Create a new concatenating spliterator with the given arguments.
045 *
046 * @param spliterators the spliterators which are concatenated
047 * @throws NullPointerException if one of the arguments are {@code null}
048 */
049 public ConcatSpliterator(final Collection<Spliterator<T>> spliterators) {
050 _spliterators = new LinkedList<>(spliterators);
051 }
052
053 @Override
054 public boolean tryAdvance(final Consumer<? super T> action) {
055 boolean advance = true;
056 if (!_spliterators.isEmpty()) {
057 final Spliterator<T> spliterator = _spliterators.peek();
058 assert spliterator != null;
059
060 if (!spliterator.tryAdvance(action)) {
061 _spliterators.removeFirst();
062 advance = !_spliterators.isEmpty();
063 }
064 } else {
065 advance = false;
066 }
067
068 return advance;
069 }
070
071 @Override
072 public Spliterator<T> trySplit() {
073 final List<Spliterator<T>> split = _spliterators.stream()
074 .map(Spliterator::trySplit)
075 .collect(Collectors.toList());
076
077 return split.stream().noneMatch(Objects::isNull)
078 ? new ConcatSpliterator<>(split)
079 : null;
080 }
081
082 @Override
083 public long estimateSize() {
084 final boolean maxValueSized = _spliterators.stream()
085 .mapToLong(Spliterator::estimateSize)
086 .anyMatch(l -> l == Long.MAX_VALUE);
087
088 return maxValueSized
089 ? Long.MAX_VALUE
090 : _spliterators.stream()
091 .mapToLong(Spliterator::estimateSize)
092 .min()
093 .orElse(1L)*_spliterators.size();
094 }
095
096 @Override
097 public int characteristics() {
098 return _spliterators.stream()
099 .mapToInt(Spliterator::characteristics)
100 .reduce(0xFFFFFFFF, (i1, i2) -> i1 & i2) &
101 ~Spliterator.SORTED;
102 }
103
104 }
|