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

com.shapesecurity.functional.data.MultiHashTable Maven / Gradle / Ivy

There is a newer version: 3.1.0
Show newest version
package com.shapesecurity.functional.data;


import com.shapesecurity.functional.F;
import com.shapesecurity.functional.F2;
import com.shapesecurity.functional.Pair;

import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;

// Map from keys to multiple values.
// This class does not distinguish between "key is present, but associated with empty list" and "key is not present". If you need that, don't use this class.
@CheckReturnValue
public class MultiHashTable { // TODO should be elsewhere... and better
    @Nonnull
    private final HashTable> data;

    private MultiHashTable(@Nonnull HashTable> data) {
        this.data = data;
    }

    @Nonnull
    public static  MultiHashTable emptyUsingEquality() {
        return new MultiHashTable<>(HashTable.emptyUsingEquality());
    }

    @Nonnull
    public static  MultiHashTable emptyUsingIdentity() {
        return new MultiHashTable<>(HashTable.emptyUsingIdentity());
    }

    @Nonnull
    @Deprecated
    public static  MultiHashTable empty() {
        return MultiHashTable.emptyUsingEquality();
    }

    @Nonnull
    @Deprecated
    public static  MultiHashTable emptyP() {
        return MultiHashTable.emptyUsingIdentity();
    }

    @Nonnull
    public MultiHashTable put(@Nonnull K key, @Nonnull V value) {
        return new MultiHashTable<>(this.data.put(key, ImmutableList.cons(value, this.data.get(key).orJust(ImmutableList.empty()))));
    }

    @Nonnull
    public MultiHashTable remove(@Nonnull K key) {
        return new MultiHashTable<>(this.data.remove(key));
    }

    @Nonnull
    public ImmutableList get(@Nonnull K key) {
        return this.data.get(key).orJust(ImmutableList.empty());
    }

    @Nonnull
    public MultiHashTable merge(@Nonnull MultiHashTable tree) { // default merge strategy: append lists.
        return this.merge(tree, ImmutableList::append);
    }

    @Nonnull
    public MultiHashTable merge(@Nonnull MultiHashTable tree, @Nonnull F2, ImmutableList, ImmutableList> merger) {
        return new MultiHashTable<>(this.data.merge(tree.data, merger));
    }

    @Nonnull
    public ImmutableList>> entries() {
        return this.data.entries();
    }

    // version: key is irrelevant
    @Nonnull
    public  HashTable toHashTable(@Nonnull F, B> conversion) {
        //return this.data.foldLeft((acc, p) -> acc.put(p.a, conversion.apply(p.b)), HashTable.empty(this.data.hasher));
        return this.toHashTable((k, vs) -> conversion.apply(vs));
    }

    // version: key is used
    @Nonnull
    public  HashTable toHashTable(@Nonnull F2, B> conversion) {
        return this.data.foldLeft((acc, p) -> acc.put(p.left, conversion.apply(p.left, p.right)), HashTable.empty(this.data.hasher));
    }

    @Nonnull
    public final ImmutableList> values() {
        return this.data.foldLeft((acc, p) -> acc.cons(p.right), ImmutableList.empty());
    }

    @Nonnull
    public final ImmutableList gatherValues() {
        return this.data.foldLeft((acc, p) -> acc.append(p.right), ImmutableList.empty());
    }

    @Nonnull
    public final  MultiHashTable mapValues(@Nonnull F f) {
        return new MultiHashTable<>(this.data.map(l -> l.map(f)));
    }
}