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

de.scravy.bedrock.Mapping Maven / Gradle / Ivy

The newest version!
package de.scravy.bedrock;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.ref.SoftReference;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * A Mapping from keys to values. A Mapping is very much like {@link java.util.Map}, but it precludes mutable operations.
 * 

* Every mapping is a function from keys to values that does know about the keys it maps. Hence a minimal * complete definition of a Mapping consists of {@link #get(Object)} and {@link #keys()}. * * @param The type of the keys. * @param The type of the values. */ public interface Mapping extends Function1, ExtendedIterable> { /** * Retrieves the value associated with the given key or Optional.empty() if the key is not mapped to any value. * * @param key The key. * @return The value which the given key is mapped to. */ @Nonnull Optional get(From key); Seq keys(); default To getOrElse(final From key, final To fallback) { return get(key).orElse(fallback); } @Nullable default To getOrNull(final From key) { return get(key).orElse(null); } @Override default To apply(final From key) { final Optional result = get(key); if (result.isPresent()) { return result.get(); } else { throw new NoSuchElementException(Objects.toString(key)); } } default int size() { return keys().length(); } default boolean isEmpty() { return keys().isEmpty(); } default Seq values() { final SeqBuilder builder = Seq.builder(); for (final From key : keys()) { builder.add(apply(key)); } return builder.result(); } @Override @Nonnull default Iterator> iterator() { return new Iterator>() { private final Iterator underlying = keys().iterator(); @Override public boolean hasNext() { return underlying.hasNext(); } @Override public Pair next() { final From nextKey = underlying.next(); return Pair.of(nextKey, apply(nextKey)); } }; } default Stream> stream() { return StreamSupport.stream(spliterator(), false); } default Map toMap() { return new AbstractMap() { private SoftReference>> entrySet = new SoftReference<>(null); @Override @Nonnull public java.util.Set> entrySet() { final java.util.Set> entrySet = this.entrySet.get(); if (entrySet == null) { final HashSet> set = new HashSet<>(); for (final From key : keys()) { set.add(Pair.of(key, apply(key))); } this.entrySet = new SoftReference<>(set); return set; } return entrySet; } }; } default void forEach(final BiConsumer action) { Objects.requireNonNull(action, "'action' must not be null"); for (final Pair t : this) { action.accept(t.fst(), t.snd()); } } static Mapping wrap(final Map map) { return new Mapping() { @Override @Nonnull public Map toMap() { return map; } @Override @Nonnull public Iterator> iterator() { return new Iterator>() { private final Iterator> underlying = map.entrySet().iterator(); @Override public boolean hasNext() { return underlying.hasNext(); } @Override public Pair next() { return Pair.of(underlying.next()); } }; } private SoftReference> keys = new SoftReference<>(null); private SoftReference> values = new SoftReference<>(null); @Nonnull @Override public Optional get(final From key) { if (map.containsKey(key)) { return Optional.ofNullable(map.get(key)); } return Optional.empty(); } @Override public Seq keys() { final Seq keys = this.keys.get(); if (keys == null) { final Seq newKeys = Seq.ofCollection(map.keySet()); this.keys = new SoftReference<>(newKeys); return newKeys; } return keys; } @Override public Seq values() { final Seq values = this.values.get(); if (values == null) { final Seq newValues = Seq.ofCollection(map.values()); this.values = new SoftReference<>(newValues); return newValues; } return values; } }; } @SuppressWarnings("unchecked") static Mapping empty() { return (Mapping) EmptyMapping.EMPTY; } class EmptyMapping implements Mapping { private static EmptyMapping EMPTY = new EmptyMapping(); @Nonnull @Override public Optional get(final K key) { return Optional.empty(); } @Override public Seq keys() { return Seq.empty(); } @Override public boolean equals(final Object obj) { if (obj == this) { return true; } return obj instanceof Mapping && ((Mapping) obj).isEmpty(); } @Override public int hashCode() { return 1; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy