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 org.jetbrains.annotations.NotNull;

// 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.
public class MultiHashTable { // TODO should be elsewhere... and better
    @NotNull
    private final HashTable> data;

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

    @NotNull
    public static  MultiHashTable empty() { // uses equality (.equals)
        return new MultiHashTable<>(HashTable.empty());
    }

    @NotNull
    public static  MultiHashTable emptyP() { // uses identity (==)
        return new MultiHashTable<>(HashTable.emptyP());
    }

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

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

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

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

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

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

    // version: key is irrelevant
    @NotNull
    public  HashTable toHashTable(@NotNull 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
    @NotNull
    public  HashTable toHashTable(@NotNull F2, B> conversion) {
        return this.data.foldLeft((acc, p) -> acc.put(p.a, conversion.apply(p.a, p.b)), HashTable.empty(this.data.hasher));
    }

    @NotNull
    public final ImmutableList> values() {
        return this.data.foldLeft((acc, p) -> acc.cons(p.b), ImmutableList.nil());
    }

    @NotNull
    public final ImmutableList gatherValues() {
        return this.data.foldLeft((acc, p) -> acc.append(p.b), ImmutableList.nil());
    }

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