com.github.tonivade.purefun.data.ImmutableMap Maven / Gradle / Ivy
/*
* Copyright (c) 2018-2019, Antonio Gabriel Muñoz Conejo
* Distributed under the terms of the MIT License
*/
package com.github.tonivade.purefun.data;
import static java.util.Collections.emptyMap;
import static java.util.Objects.requireNonNull;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.github.tonivade.purefun.Consumer2;
import com.github.tonivade.purefun.Equal;
import com.github.tonivade.purefun.Function1;
import com.github.tonivade.purefun.Matcher1;
import com.github.tonivade.purefun.Operator2;
import com.github.tonivade.purefun.Producer;
import com.github.tonivade.purefun.Tuple;
import com.github.tonivade.purefun.Tuple2;
import com.github.tonivade.purefun.type.Option;
public interface ImmutableMap extends Iterable> {
Map toMap();
ImmutableMap put(K key, V value);
ImmutableMap putAll(ImmutableSet> other);
ImmutableMap remove(K key);
Option get(K key);
Sequence values();
ImmutableSet keys();
ImmutableSet> entries();
ImmutableMap merge(K key, V value, Operator2 merger);
int size();
@Override
default Iterator> iterator() {
return entries().iterator();
}
default void forEach(Consumer2 consumer) {
entries().forEach(tuple -> consumer.accept(tuple.get1(), tuple.get2()));
}
default ImmutableMap map(Function1 keyMapper, Function1 valueMapper) {
return ImmutableMap.from(entries().map(tuple -> tuple.map(keyMapper, valueMapper)));
}
default ImmutableMap mapKeys(Function1 mapper) {
return ImmutableMap.from(entries().map(tuple -> tuple.map1(mapper)));
}
default ImmutableMap mapValues(Function1 mapper) {
return ImmutableMap.from(entries().map(tuple -> tuple.map2(mapper)));
}
default ImmutableMap filterKeys(Matcher1 filter) {
return ImmutableMap.from(entries().filter(tuple -> filter.match(tuple.get1())));
}
default ImmutableMap filterValues(Matcher1 filter) {
return ImmutableMap.from(entries().filter(tuple -> filter.match(tuple.get2())));
}
default boolean containsKey(K key) {
return get(key).isPresent();
}
default ImmutableMap putIfAbsent(K key, V value) {
if (containsKey(key)) {
return this;
}
return put(key, value);
}
default V getOrDefault(K key, Producer supplier) {
return get(key).getOrElse(supplier);
}
default boolean isEmpty() {
return size() == 0;
}
@SafeVarargs
static ImmutableMap of(Tuple2 ... entries) {
return from(ImmutableSet.of(entries));
}
static Tuple2 entry(K key, V value) {
return Tuple2.of(key, value);
}
static ImmutableMap from(Map map) {
return new JavaBasedImmutableMap<>(map);
}
static ImmutableMap empty() {
return new JavaBasedImmutableMap<>(emptyMap());
}
static ImmutableMap from(Stream> entries) {
return from(ImmutableSet.from(entries));
}
static ImmutableMap from(ImmutableSet> entries) {
return new JavaBasedImmutableMap<>(entries.stream()
.collect(Collectors.toMap(Tuple2::get1, Tuple2::get2)));
}
static Builder builder() {
return new Builder<>();
}
final class Builder {
private final Map map = new HashMap<>();
private Builder() { }
public Builder put(K key, V value) {
map.put(key, value);
return this;
}
public ImmutableMap build() {
return ImmutableMap.from(map);
}
}
final class JavaBasedImmutableMap implements ImmutableMap, Serializable {
private static final long serialVersionUID = -1236334562860351635L;
private final Map backend;
private JavaBasedImmutableMap(Map backend) {
this.backend = requireNonNull(backend);
}
@Override
public Map toMap() {
return new HashMap<>(backend);
}
@Override
public int size() {
return backend.size();
}
@Override
public ImmutableMap put(K key, V value) {
Map newMap = toMap();
newMap.put(key, value);
return new JavaBasedImmutableMap<>(newMap);
}
@Override
public ImmutableMap putAll(ImmutableSet> other) {
Map newMap = toMap();
newMap.putAll(ImmutableMap.from(other).toMap());
return new JavaBasedImmutableMap<>(newMap);
}
@Override
public ImmutableMap remove(K key) {
Map newMap = toMap();
newMap.remove(key);
return new JavaBasedImmutableMap<>(newMap);
}
@Override
public Option get(K key) {
return Option.of(() -> backend.get(key));
}
@Override
public ImmutableMap merge(K key, V value, Operator2 merger) {
Map newMap = toMap();
newMap.merge(key, value, merger::apply);
return new JavaBasedImmutableMap<>(newMap);
}
@Override
public Sequence values() {
return ImmutableList.from(backend.values());
}
@Override
public ImmutableSet keys() {
return ImmutableSet.from(backend.keySet());
}
@Override
public ImmutableSet> entries() {
return ImmutableSet.from(backend.entrySet()).map(Tuple::from);
}
@Override
public int hashCode() {
return Objects.hash(backend);
}
@Override
public boolean equals(Object obj) {
return Equal.of(this)
.append((a, b) -> Objects.equals(a.backend, b.backend))
.applyTo(obj);
}
@Override
public String toString() {
return "ImmutableMap(" + backend + ")";
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy