/** * Copyright (c) Rich Hickey. All rights reserved. * The use and distribution terms for this software are covered by the * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) * which can be found in the file epl-v10.html at the root of this distribution. * By using this software in any fashion, you are agreeing to be bound by * the terms of this license. * You must not remove this notice, or any other, from this software. **/ /* rich Mar 3, 2008 */ package com.trifork.clj_ds; import java.util.Iterator; import java.util.List; import java.util.Map; public class PersistentHashSet<T> extends APersistentSet<T> implements IObj, IEditableCollection<T> { static public final PersistentHashSet EMPTY = new PersistentHashSet(null, PersistentHashMap.EMPTY); @SuppressWarnings("unchecked") static public final <T> PersistentHashSet<T> emptySet() { return EMPTY; } final IPersistentMap _meta; public static <T> PersistentHashSet<T> create(T... init){ PersistentHashSet<T> ret = EMPTY; for(int i = 0; i < init.length; i++) { ret = (PersistentHashSet<T>) ret.cons(init[i]); } return ret; } public static <T> PersistentHashSet<T> create(List<? extends T> init){ PersistentHashSet<T> ret = EMPTY; for(T key : init) { ret = (PersistentHashSet<T>) ret.cons(key); } return ret; } static public <T> PersistentHashSet<T> create(ISeq<? extends T> items){ PersistentHashSet<T> ret = EMPTY; for(; items != null; items = items.next()) { ret = (PersistentHashSet<T>) ret.cons(items.first()); } return ret; } public static <T> PersistentHashSet<T> createWithCheck(T ... init){ PersistentHashSet<T> ret = EMPTY; for(int i = 0; i < init.length; i++) { ret = (PersistentHashSet<T>) ret.cons(init[i]); if(ret.count() != i + 1) throw new IllegalArgumentException("Duplicate key: " + init[i]); } return ret; } public static <T> PersistentHashSet<T> createWithCheck(List<? extends T> init){ PersistentHashSet<T> ret = EMPTY; int i=0; for(T key : init) { ret = (PersistentHashSet<T>) ret.cons(key); if(ret.count() != i + 1) throw new IllegalArgumentException("Duplicate key: " + key); ++i; } return ret; } static public <T> PersistentHashSet<T> createWithCheck(ISeq<? extends T> items){ PersistentHashSet<T> ret = EMPTY; for(int i=0; items != null; items = items.next(), ++i) { ret = (PersistentHashSet<T>) ret.cons(items.first()); if(ret.count() != i + 1) throw new IllegalArgumentException("Duplicate key: " + items.first()); } return ret; } PersistentHashSet(IPersistentMap meta, IPersistentMap impl){ super(impl); this._meta = meta; } public Iterator<T> iterator(){ return new Iterator<T>() { final Iterator<Map.Entry> iterator = impl.iterator(); public boolean hasNext() { return iterator.hasNext(); } public T next() { Map.Entry n = iterator.next(); return (T) n.getKey(); } @Override public void remove() { throw new UnsupportedOperationException(); } }; } public IPersistentSet<T> disjoin(T key) throws Exception{ if(contains(key)) return new PersistentHashSet<T>(meta(),impl.without(key)); return this; } public IPersistentSet<T> cons(T o){ if(contains(o)) return this; return new PersistentHashSet<T>(meta(),impl.assoc(o,o)); } public IPersistentCollection<T> empty(){ return EMPTY.withMeta(meta()); } public PersistentHashSet<T> withMeta(IPersistentMap meta){ return new PersistentHashSet<T>(meta, impl); } public ITransientCollection<T> asTransient() { return new TransientHashSet<T>(((PersistentHashMap) impl).asTransient()); } public IPersistentMap meta(){ return _meta; } static final class TransientHashSet<T> extends ATransientSet<T> { TransientHashSet(ITransientMap impl) { super(impl); } public IPersistentCollection<T> persistent() { return new PersistentHashSet<T>(null, impl.persistentMap()); } } }