All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fizzed.crux.util.MaybeStream Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2018 Fizzed, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.fizzed.crux.util;

import java.util.Collection;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.function.BiConsumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * A null-safe way of working with iterables and arrays as streams.  Useful
 * for iterating with indexes too :-)
 * 
 * @author jjlauer
 * @param  The type of Maybe
 */
public class MaybeStream implements Iterable {
    
    final private Iterable values;
    
    protected MaybeStream(Iterable values) {
        this.values = values;
    }

    public Stream get() {
        if (values == null) {
            throw new NoSuchElementException("No values present");
        }
        return this.jvmStream();
    }
    
    public Stream jvmStream() {
        if (values == null) {
            return Stream.empty();
        }
        // optimized for collections (e.g. List)
        if (values instanceof Collection) {
            return ((Collection)values).stream();
        } else {
            return StreamSupport.stream(this.values.spliterator(), false);
        }
    }
    
    @Deprecated
    public Stream stream() {
        return this.jvmStream();
    }
    
    public Maybe first() {
        return Maybe.of(MoreObjects.first(this.values));
    }
    
    public Maybe last() {
        return Maybe.of(MoreObjects.last(this.values));
    }
    
    @Override
    public Iterator iterator() {
        if (values == null) {
            return new ArrayIterator<>(null);   // empty
        }
        // optimized for collections (e.g. List)
        if (values instanceof Collection) {
            return ((Collection)values).iterator();
        } else {
            return values.iterator();
        }
    }
    
    public void forEach(BiConsumer consumer) {
        if (values != null) {
            IterableIter iter = new IterableIter<>(this.values);
            iter.forEach(consumer);
        }
    }
    
    public boolean isPresent() {
        return this.values != null;
    }
    
    public boolean isAbsent() {
        return this.values == null;
    }

    static public  MaybeStream empty() {
        return new MaybeStream<>(null);
    }
    
    static public  MaybeStream of(T[] values) {
        if (values == null) {
            return empty();
        }
        return maybeStream(new ArrayIterable<>(values));
    }
    
    static public  MaybeStream of(Iterable values) {
        return maybeStream(values);
    }
    
    static public  MaybeStream maybeStream(T[] values) {
        return MaybeStream.of(values);
    }
    
    static public  MaybeStream maybeStream(Iterable value) {
        return new MaybeStream<>(value);
    }
    
    // helpers
    
    static public class ArrayIterable implements Iterable {
        
        private final V[] values;

        public ArrayIterable(V[] values) {
            this.values = values;
        }
        
        @Override
        public Iterator iterator() {
            return new ArrayIterator<>(this.values);
        }
        
    }
    
    static public class ArrayIterator implements Iterator {

        private final V[] values;
        private int index;

        public ArrayIterator(V[] values) {
            this.values = values;
            this.index = 0;
        }
        
        @Override
        public boolean hasNext() {
            return this.values != null && this.index < this.values.length;
        }

        @Override
        public V next() {
            if (this.values == null) {
                return null;
            }
            V value = this.values[this.index];
            this.index++;
            return value;
        }
        
    }
    
    static public interface Iter {
        void forEach(BiConsumer consumer);
    }
    
    static public class IterableIter implements Iter {
        
        private final Iterable values;

        public IterableIter(Iterable values) {
            this.values = values;
        }

        @Override
        public void forEach(BiConsumer consumer) {
            if (this.values == null) {
                return;
            }
            final Iterator iterator = this.values.iterator();
            int i = 0;
            while (iterator.hasNext()) {
                V value = iterator.next();
                consumer.accept(value, i);
                i++;
            }
        }
    }
    
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy