/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2001-2008, Open Source Geospatial Foundation (OSGeo) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ package org.geotools.util; /** * A canonical set of objects, used to optimize memory use. * The operation of this set is similar in spirit to the {@link String#intern} method. * The following example shows a convenient way to use {@code CanonicalSet} as an * internal pool of immutable objects. * * <blockquote><pre> * public Foo create(String definition) { * Foo created = new Foo(definition); * return (Foo) canonicalSet.unique(created); * } * </pre></blockquote> * * The {@code CanonicalSet} has a {@link #get} method that is not part of the {@link java.util.Set} * interface. This {@code get} method retrieves an entry from this set that is equals to * the supplied object. The {@link #unique} method combines a {@code get} followed by a * {@code put} operation if the specified object was not in the set. * <p> * The set of objects is held by weak references as explained in {@link WeakHashSet}. * The {@code CanonicalSet} class is thread-safe. * * @param <E> The type of elements in the set. * * @since 2.4 * * @source $URL$ * @version $Id$ * @author Martin Desruisseaux (IRD) * @author Jody Garnett */ public class CanonicalSet<E> extends WeakHashSet<E> { /** * Constructs a {@code CanonicalSet}. * * @deprecated Use {@link #newInstance} instead. */ public CanonicalSet() { } /** * Constructs a {@code CanonicalSet} for elements of the specified type. * * @param type The type of elements in the set. * * @since 2.5 */ protected CanonicalSet(final Class<E> type) { super(type); } /** * Constructs a {@code CanonicalSet} for elements of the specified type. * * @param <E> The type of elements in the set. * @param type The type of elements in the set. * @return An initially empty set for elements of the given type. * * @since 2.5 */ public static <E> CanonicalSet<E> newInstance(final Class<E> type) { return new CanonicalSet<E>(type); } /** * Returns an object equals to the specified object, if present. If * this set doesn't contains any object equals to {@code object}, * then this method returns {@code null}. * * @param <T> The type of the element to get. * @param object The element to get. * @return An element equals to the given one if already presents in the set, * or {@code null} otherwise. * * @see #unique(Object) */ public synchronized <T extends E> T get(final T object) { return intern(object, GET); } /** * Returns an object equals to {@code object} if such an object already exist in this * {@code CanonicalSet}. Otherwise, adds {@code object} to this {@code CanonicalSet}. * This method is equivalents to the following code: * * <blockquote><pre> * if (object != null) { * Object current = get(object); * if (current != null) { * return current; * } else { * add(object); * } * } * return object; * </pre></blockquote> * * @param <T> The type of the element to get. * @param object The element to get or to add in the set if not already presents. * @return An element equals to the given one if already presents in the set, * or the given {@code object} otherwise. */ public synchronized <T extends E> T unique(final T object) { return intern(object, INTERN); } /** * Iteratively call {@link #unique(Object)} for an array of objects. * This method is equivalents to the following code: * * <blockquote><pre> * for (int i=0; i<objects.length; i++) { * objects[i] = unique(objects[i]); * } * </pre></blockquote> * * @param objects * On input, the objects to add to this set if not already present. On output, * elements that are {@linkplain Object#equals equal}, but where every reference * to an instance already presents in this set has been replaced by a reference * to the existing instance. */ public synchronized void uniques(final E[] objects) { for (int i=0; i<objects.length; i++) { objects[i] = intern(objects[i], INTERN); } } }