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

edu.isi.nlp.collections.LaxImmutableMapBuilder Maven / Gradle / Ivy

The newest version!
package edu.isi.nlp.collections;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;
import java.util.Comparator;
import java.util.Map;
import javax.annotation.Nullable;

/**
 * Guava's {@link com.google.common.collect.ImmutableMap.Builder} disallows adding the same key
 * twice, even with the same value. In many situations this is inconvenient, so this interface is
 * the parent of builders which relax this constraint in various ways. See {@link
 * MapUtils#immutableMapBuilderAllowingSameEntryTwice()}, {@link
 * MapUtils#immutableMapBuilderIgnoringDuplicates()}, and {@link
 * MapUtils#immutableMapBuilderResolvingDuplicatesBy(Comparator)}.
 *
 * 

You might think that this is unnecessary because you can simply build your map using e.g. a * {@link java.util.HashMap} and then call {@link ImmutableMap#copyOf(Iterable)}, but that loses * {@link ImmutableMap.Builder}'s very nice determinism guarantees. * *

These builders are generally less efficient than {@link ImmutableMap.Builder}, so be cautious * using them in performance-sensitive code. */ public interface LaxImmutableMapBuilder { LaxImmutableMapBuilder put(K key, V value); LaxImmutableMapBuilder putAll(Map map); LaxImmutableMapBuilder putAll( Iterable> entries); /** See {@link ImmutableMap.Builder#orderEntriesByValue(Comparator)} */ LaxImmutableMapBuilder orderEntriesByValue(Comparator valueComparator); ImmutableMap build(); } /** Implementation for {@link LaxImmutableMapBuilder}s which never need to change their mind. */ final class MonotonicLaxImmutableMapBuilder implements LaxImmutableMapBuilder { private final Map mappingsSeen = Maps.newHashMap(); private final ImmutableMap.Builder innerBuilder = ImmutableMap.builder(); private final boolean keepFirst; MonotonicLaxImmutableMapBuilder(final boolean keepFirst) { this.keepFirst = keepFirst; } @Override public LaxImmutableMapBuilder put(K key, V value) { checkNotNull(key); checkNotNull(value); final V existingMapping = mappingsSeen.get(key); if (null == existingMapping) { mappingsSeen.put(key, value); innerBuilder.put(key, value); } else if (existingMapping.equals(value)) { // do nothing } else if (keepFirst) { // do nothing, we have been requested to silently keep the first value } else { throw new IllegalArgumentException( "Refusing to add two mappings for the key " + key + ": " + existingMapping + " and " + value); } return this; } @Override public LaxImmutableMapBuilder putAll(Map map) { for (final Map.Entry e : map.entrySet()) { put(e.getKey(), e.getValue()); } return this; } @Override public LaxImmutableMapBuilder putAll( Iterable> entries) { for (final Map.Entry e : entries) { put(e.getKey(), e.getValue()); } return this; } /** See {@link ImmutableMap.Builder#orderEntriesByValue(Comparator)} */ @Override public LaxImmutableMapBuilder orderEntriesByValue(Comparator valueComparator) { innerBuilder.orderEntriesByValue(valueComparator); return this; } @Override public ImmutableMap build() { return innerBuilder.build(); } } /** Implementation for {@link LaxImmutableMapBuilder}s which do need to change their mind. */ final class NonMonotonicLaxImmutableMapBuilder implements LaxImmutableMapBuilder { private final ImmutableSet.Builder orderKeysSeenIn = ImmutableSet.builder(); private final Map mappingsSeen = Maps.newHashMap(); private final Ordering conflictComparator; private @Nullable Comparator immutableMapEntryOrdering = null; NonMonotonicLaxImmutableMapBuilder(final Ordering conflictComparator) { this.conflictComparator = checkNotNull(conflictComparator); } @Override public LaxImmutableMapBuilder put(K key, V value) { checkNotNull(key); checkNotNull(value); final V existingMapping = mappingsSeen.get(key); if (null == existingMapping) { mappingsSeen.put(key, value); orderKeysSeenIn.add(key); } else if (existingMapping.equals(value)) { // do nothing } else { // add only if new value is larger by the provided comparator if (conflictComparator.max(existingMapping, value).equals(value)) { mappingsSeen.put(key, value); } } return this; } @Override public LaxImmutableMapBuilder putAll(Map map) { for (final Map.Entry e : map.entrySet()) { put(e.getKey(), e.getValue()); } return this; } @Override public LaxImmutableMapBuilder putAll( Iterable> entries) { for (final Map.Entry e : entries) { put(e.getKey(), e.getValue()); } return this; } /** See {@link ImmutableMap.Builder#orderEntriesByValue(Comparator)} */ @Override public LaxImmutableMapBuilder orderEntriesByValue(Comparator valueComparator) { this.immutableMapEntryOrdering = checkNotNull(valueComparator); return this; } @Override public ImmutableMap build() { final ImmutableMap.Builder ret = ImmutableMap.builder(); if (immutableMapEntryOrdering != null) { ret.orderEntriesByValue(immutableMapEntryOrdering); } for (final K key : orderKeysSeenIn.build()) { ret.put(key, mappingsSeen.get(key)); } return ret.build(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy