/* * Copyright 2014 Grow Bit * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.turbogwt.core.collections; import com.google.gwt.core.client.JsArrayString; import java.util.AbstractSet; import java.util.Iterator; import java.util.NoSuchElementException; /** * An implementation of Set based on {@link JsHashTable}. * <p> * * This class indexes the objects by resorting to their hashCode method.<br> * In order to use it, the values must implement hashCode consistently. * * @param <T> Type of set values * * @author Danilo Reinert */ public class JsHashSet<T> extends AbstractSet<T> { private final JsHashTable<T> hashTable = JsHashTable.create(); private int size; public JsHashSet() { } public JsHashSet(Iterable<T> iterable) { for (T t : iterable) { add(t); } } @Override public int size() { return size; } @Override @SuppressWarnings("unchecked") public boolean contains(Object o) { checkNotNull(o); return hashTable.contains((T) o); } @Override public Iterator<T> iterator() { return new Itr(); } @Override public Object[] toArray() { return hashTable.values().toArray(); } @Override @SuppressWarnings("unchecked") public <E> E[] toArray(E[] a) { JsArray<T> jsArray = hashTable.values(); if (a != null && a.length >= jsArray.length()) { for (int i = 0; i < jsArray.length(); i++) { E e = (E) jsArray.get(i); a[i] = e; } return a; } return (E[]) jsArray.toArray(); } @Override public boolean add(T t) { checkNotNull(t); if (contains(t)) { return false; } ++size; hashTable.put(t); return true; } @Override @SuppressWarnings("unchecked") public boolean remove(Object o) { checkNotNull(o); --size; return hashTable.remove((T) o); } @Override public void clear() { hashTable.clear(); } private void checkNotNull(Object o) { if (o == null) throw new NullPointerException("This Set does not support null values"); } private class Itr implements Iterator<T> { private JsArrayString keys = hashTable.hashCodes(); private int cursor; // index of next element to return private T lastRet; private Iterator<T> bucketItr = new JsArrayIterator<T>(hashTable.get(keys.get(cursor))); public boolean hasNext() { return cursor != keys.length() && bucketItr.hasNext(); } @Override public T next() { int i = cursor; if (i >= keys.length()) throw new NoSuchElementException(); if (!bucketItr.hasNext()) { bucketItr = new JsArrayIterator<T>(hashTable.get(keys.get(cursor))); cursor = i + 1; } lastRet = bucketItr.next(); return lastRet; } @Override public void remove() { if (lastRet == null) throw new IllegalStateException(); bucketItr.remove(); JsHashSet.this.remove(lastRet); lastRet = null; } } }