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

com.blazegraph.gremlin.util.Lambdas Maven / Gradle / Ivy

/**
Copyright (C) SYSTAP, LLC DBA Blazegraph 2006-2016.  All rights reserved.

Contact:
     SYSTAP, LLC DBA Blazegraph
     2501 Calvert ST NW #106
     Washington, DC 20008
     [email protected]

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/
package com.blazegraph.gremlin.util;

import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.stream.Collector;
import java.util.stream.Collectors;

/**
 * Lambda helpers.
 * 
 * @author mikepersonick
 */
public interface Lambdas {

    /**
     * Create a "distinct by property" predicate for filtering.
     * 
     * Usage:
     * Stream distinct Person objects by name:
     * {@code
     *    persons.stream().filter(distinctByKey(p -> p.getName());
     * }
     * 
     * @return predicate (thread-safe)
     */
    public static  Predicate distinctByKey(
            final Function keyExtractor) {
        final Map seen = new ConcurrentHashMap<>();
        return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
    }
    
    /**
     * Collect an Map.Entry stream into a Map.
     * 
     * @param  the type of key in the incoming entry stream
     * @param  the type of value in the incoming entry stream
     */
    public static  Collector, ?, Map> toMap() {
        return Collectors.toMap(Entry::getKey, Entry::getValue);
    }
    
    /**
     * Collect an Map.Entry stream into a Map using the specified map supplier.
     * 
     * @param  the type of key in the incoming entry stream
     * @param  the type of value in the incoming entry stream
     * @param  the type of the resulting {@code Map}
     */
    public static > 
    Collector, ?, M> toMap(Supplier mapSupplier) {
        return Collectors.toMap(
                Entry::getKey, 
                Entry::getValue,
                /*
                 * We should never need to merge values (assuming the entry 
                 * stream has distinct keys).
                 */
                (a, b) -> { throw new IllegalStateException(
                                    String.format("Duplicate key %s", a)); },
                mapSupplier
                );
    }
    
    /**
     * This is the missing toMap() method on the Collectors class - specify
     * the key mapper, the value mapper, and the map supplier without having
     * to specify the value merge function.
     * 
     * @param  the type of the input elements
     * @param  the output type of the key mapping function
     * @param  the output type of the value mapping function
     * @param  the type of the resulting {@code Map}
     */
    public static >
    Collector toMap(Function keyMapper,
                             Function valueMapper,
                             Supplier mapSupplier) {
        return Collectors.toMap(
                keyMapper, 
                valueMapper,
                (a,b) -> { throw new IllegalStateException(
                                    String.format("Duplicate key %s", a)); },
                mapSupplier
                );
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy