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

com.jmatio.common.DeterministicKeyMap Maven / Gradle / Ivy

There is a newer version: 3.1.1
Show newest version
/*
 * Code licensed under new-style BSD (see LICENSE).
 * All code up to tags/original: Copyright (c) 2006, Wojciech Gradkowski
 * All code after tags/original: Copyright (c) 2015, DiffPlug
 */
package com.jmatio.common;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * A map implementation which guarantees that all of its iterators
 * (keySet(), values(), and entrySet()) will be in the same order
 * as the keyOrder set which is passed in the constructor.
 * 
 * The keySet must contain all of the keys in the delegate, but it's
 * okay if the keySet contains more.
 * 
 * Useful in MLObject and MLStruct for ensuring that arrays have
 * their fields in the same order.
 */
public class DeterministicKeyMap extends ForwardingMap {
	private final Set keyOrder;

	/**
	 * 
	 * @param keyOrder A set which must always contain all of the keys in delegate, and may contain more.
	 * @param delegate An underlying map.
	 */
	public DeterministicKeyMap(Set keyOrder, Map delegate) {
		super(delegate);
		this.keyOrder = keyOrder;
	}

	/** Returns the keyset of this map in the same order as keyOrder. */
	@SuppressWarnings("unchecked")
	@Override
	public Set keySet() {
		return new DeterministicSet(delegate.keySet(), (Function) identity);
	}

	/** Returns the values of this map in the same order as keyOrder. */
	@Override
	public Collection values() {
		return new DeterministicCollection(delegate.values(), new Function() {
			@Override
			public V apply(K input) {
				return delegate.get(input);
			}
		});
	}

	/** Returns the entries of this map in the same order as keyOrder. */
	@Override
	public Set> entrySet() {
		return new DeterministicSet>(delegate.entrySet(), new Function>() {
			@Override
			public Map.Entry apply(final K key) {
				return new Map.Entry() {
					@Override
					public K getKey() {
						return key;
					}

					@Override
					public V getValue() {
						return delegate.get(key);
					}

					@Override
					public V setValue(V value) {
						return delegate.put(key, value);
					}
				};
			}
		});
	}

	@Override
	public boolean equals(Object other) {
		return super.equals(other);
	}

	@Override
	public int hashCode() {
		return super.hashCode();
	}

	/** Java didn't find functional programming until Java 8. */
	static interface Function {
		R apply(T input);
	}

	static final Function identity = new Function() {
		@Override
		public Object apply(Object input) {
			return input;
		}
	};

	/** DeterministicCollection which guarantees a Set delegate. */
	class DeterministicSet extends DeterministicCollection implements Set {
		DeterministicSet(Set delegate, Function keyToValue) {
			super(delegate, keyToValue);
		}
	}

	/** A collection which iterates over the key set, transformed into values using the given function. */
	class DeterministicCollection extends ForwardingCollection {
		Function keyToValue;

		DeterministicCollection(Collection delegate, Function keyToValue) {
			super(delegate);
			this.keyToValue = keyToValue;
		}

		@Override
		public Iterator iterator() {
			final Iterator iterByKey = keyOrder.iterator();
			return new AbstractIterator() {
				@Override
				protected T computeNext() {
					while (iterByKey.hasNext()) {
						K nextKey = iterByKey.next();
						T value = keyToValue.apply(nextKey);
						if (delegate.contains(value)) {
							return value;
						}
					}
					return endOfData();
				}
			};
		}

		@Override
		public boolean equals(Object other) {
			return super.equals(other);
		}

		@Override
		public int hashCode() {
			return super.hashCode();
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy