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

net.java.truecommons.shed.CanonicalStringSet Maven / Gradle / Ivy

There is a newer version: 2.5.0
Show newest version
/*
 * Copyright (C) 2005-2012 Schlichtherle IT Services.
 * All rights reserved. Use is subject to license terms.
 */
package net.java.truecommons.shed;

import java.util.*;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.NotThreadSafe;

/**
 * An abstract set of the canonical string representation of objects in
 * natural sort order.
 * An object is canonicalized by the idempotent function
 * {@link Canonicalizer#map}.
 * 

* Canonical string sets can be converted from and to string lists by using * {@link #addAll(String)} and {@link #toString()}. * A string list is a string which consists of zero or more elements * which are separated by the separator character provided to the * constructor. * Note that in general, a string list is just a sequence of strings elements. * In particular, a string list may be empty (but not {@code null}) and * its elements don't have to be in canonical form, may be duplicated in the * list and may be listed in arbitrary order. * However, string lists have a canonical form, too: * A string list in canonical form (or canonical string list for short) * is a string list which contains only canonical strings in natural sort order * and does not contain any duplicates (so it's actually a set). *

* Unless otherwise documented, all {@link java.util.Set} methods work on the * canonical form of the string elements in this set. *

* Null elements are not permitted in this set. * * @author Christian Schlichtherle */ @NotThreadSafe public class CanonicalStringSet extends AbstractSet { /** The canonicalizer for strings. */ private final Canonicalizer canonicalizer; /** The separator for string lists. */ private final char separator; /** The sorted map which implements the behaviour of this class. */ private final Set set = new TreeSet<>(); /** * Constructs a new, empty set of canonical strings. * * @param canonicalizer the idempotent function to use for canonicalizing * strings. * @param separator The separator character to use for string lists. */ public CanonicalStringSet( final Canonicalizer canonicalizer, final char separator) { this.canonicalizer = Objects.requireNonNull(canonicalizer); this.separator = separator; } @Override public boolean isEmpty() { return set.isEmpty(); } @Override public int size() { return set.size(); } @Override public Iterator iterator() { return set.iterator(); } @Override public Object[] toArray() { return set.toArray(); } @Override public T[] toArray(T[] a) { return set.toArray(a); } /** * Returns the string list in canonical form for this canonical string set. * If this canonical string set is empty, an empty string is returned. */ @Override public String toString() { final int capacity = size() * 11; if (0 >= capacity) return ""; final StringBuilder s = new StringBuilder(capacity); for (final String string : this) { if (s.length() > 0) s.append(separator); s.append(string); } return s.toString(); } /** * {@inheritDoc} *

* The implementation in the class {@link CanonicalStringSet} first * canonicalizes the given parameter before the operation is continued. */ @Override public boolean contains(@Nullable Object o) { return set.contains(canonicalizer.map(o)); } /** * {@inheritDoc} *

* The implementation in the class {@link CanonicalStringSet} first * canonicalizes the given parameter before the operation is continued. */ @Override public boolean add(@Nullable String e) { return set.add(canonicalizer.map(e)); } /** * {@inheritDoc} *

* The implementation in the class {@link CanonicalStringSet} first * canonicalizes the given parameter before the operation is continued. */ @Override public boolean remove(@Nullable Object o) { return set.remove(canonicalizer.map(o)); } @Override public void clear() { set.clear(); } /** * Tests if all canonical strings in the given set are contained in this * set. * An empty set is considered to be a true subset of this set. * * @param set A non-null set of canonical strings. * @return {@code true} Iff all strings in the given set are contained * in this set. */ public boolean containsAll(final CanonicalStringSet set) { return this.set.containsAll(set.set); } /** * Tests if the canonical form of all strings in the given string list * is contained in this set. * If a string in the list does not have a canonical form, it's skipped. * This implies that if the list is empty or entirely consists of strings * which do not have a canonical form, {@code true} is returned. * In other words, an empty set is considered to be a true subset of this * set. * * @param list a non-null string list. * @return {@code true} Iff the canonical form of all strings in the * given string list is contained in this set. */ public boolean containsAll(final String list) { Iterator i = new CanonicalStringIterator(list); while (i.hasNext()) if (!set.contains(i.next())) return false; return true; } /** * Adds all canonical strings in the given set to this set after they have * been canonicalized by this set again. * * @param set a non-null set of canonical strings. * @return {@code true} Iff this set of canonicalized strings has * changed as a result of the call. */ public boolean addAll(final CanonicalStringSet set) { boolean changed = false; for (String s : set.set) changed |= add(s); return changed; } /** * Adds the canonical form of all strings in the given list to this set. * If a string in the list does not have a canonical form, it's skipped. * * @param list a non-null string list. * @return {@code true} Iff this set of canonicalized strings has * changed as a result of the call. */ public boolean addAll(final String list) { boolean changed = false; Iterator i = new CanonicalStringIterator(list); while (i.hasNext()) changed |= set.add(i.next()); return changed; } /** * Retains all canonical strings in the given set in this set. * * @param set a non-null set of canonical strings. * @return {@code true} Iff this set changed as a result of the call. */ public boolean retainAll(CanonicalStringSet set) { return this.set.retainAll(set.set); } /** * Retains the canonical form of all strings in the given list in this set. * If a string in the list does not have a canonical form, it's skipped. * * @param list a non-null string list. * @return {@code true} Iff this set changed as a result of the call. */ public boolean retainAll(final String list) { final CanonicalStringSet set = new CanonicalStringSet(canonicalizer, separator); set.addAll(list); return this.set.retainAll(set); } /** * Removes all canonical strings in the given set from this set. * * @param set a non-null set of strings. * @return {@code true} Iff this set changed as a result of the call. */ public boolean removeAll(CanonicalStringSet set) { return this.set.removeAll(set.set); } /** * Removes the canonical form of all strings in the given list from this set. * If a string in the list does not have a canonical form, it's skipped. * * @param list a non-null string list. * @return {@code true} Iff this set changed as a result of the call. */ public boolean removeAll(final String list) { boolean changed = false; Iterator i = new CanonicalStringIterator(list); while (i.hasNext()) changed |= set.remove(i.next()); return changed; } /** * An idempotent function which maps an arbitrary object to its canonical * string representation. * * @see { private final StringTokenizer tokenizer; private @CheckForNull String canonical; private CanonicalStringIterator(final String list) { tokenizer = new StringTokenizer(list, "" + separator); // NOI18N advance(); } private void advance() { while (tokenizer.hasMoreTokens()) if (null != (canonical = canonicalizer.map(tokenizer.nextToken()))) return; canonical = null; // no such element } @Override public boolean hasNext() { return null != canonical; } @Override public String next() { final String canonical = this.canonical; if (null == canonical) throw new NoSuchElementException(); advance(); return canonical; } @Override public void remove() { throw new UnsupportedOperationException(); } } // CanonicalStringIterator }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy