Collections/src/dorkbox/collections/OrderedSet.java

170 lines
4.3 KiB
Java

/*******************************************************************************
* Copyright 2011 LibGDX.
* Mario Zechner <badlogicgames@gmail.com>
* Nathan Sweet <nathan.sweet@gmail.com>
*
* 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 dorkbox.collections;
import java.util.NoSuchElementException;
/** An {@link ObjectSet} that also stores keys in an {@link Array} using the insertion order. {@link #iterator() Iteration} is
* ordered and faster than an unordered set. Keys can also be accessed and the order changed using {@link #orderedItems()}. There
* is some additional overhead for put and remove. When used for faster iteration versus ObjectSet and the order does not actually
* matter, copying during remove can be greatly reduced by setting {@link Array#ordered} to false for
* {@link OrderedSet#orderedItems()}.
* @author Nathan Sweet */
@SuppressWarnings({"unchecked", "rawtypes"})
public class OrderedSet<T> extends ObjectSet<T> {
final Array<T> items;
OrderedSetIterator iterator1, iterator2;
public OrderedSet () {
items = new Array();
}
public OrderedSet (int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
items = new Array(capacity);
}
public OrderedSet (int initialCapacity) {
super(initialCapacity);
items = new Array(capacity);
}
public OrderedSet (OrderedSet set) {
super(set);
items = new Array(capacity);
items.addAll(set.items);
}
@Override
public boolean add (T key) {
if (!super.add(key)) return false;
items.add(key);
return true;
}
public boolean add (T key, int index) {
if (!super.add(key)) {
items.removeValue(key, true);
items.insert(index, key);
return false;
}
items.insert(index, key);
return true;
}
@Override
public boolean remove (T key) {
if (!super.remove(key)) return false;
items.removeValue(key, false);
return true;
}
public T removeIndex (int index) {
T key = items.removeIndex(index);
super.remove(key);
return key;
}
@Override
public void clear (int maximumCapacity) {
items.clear();
super.clear(maximumCapacity);
}
@Override
public void clear () {
items.clear();
super.clear();
}
public Array<T> orderedItems () {
return items;
}
@Override
public OrderedSetIterator<T> iterator () {
if (iterator1 == null) {
iterator1 = new OrderedSetIterator(this);
iterator2 = new OrderedSetIterator(this);
}
if (!iterator1.valid) {
iterator1.reset();
iterator1.valid = true;
iterator2.valid = false;
return iterator1;
}
iterator2.reset();
iterator2.valid = true;
iterator1.valid = false;
return iterator2;
}
@Override
public String toString () {
if (size == 0) return "{}";
T[] items = this.items.items;
StringBuilder buffer = new StringBuilder(32);
buffer.append('{');
buffer.append(items[0]);
for (int i = 1; i < size; i++) {
buffer.append(", ");
buffer.append(items[i]);
}
buffer.append('}');
return buffer.toString();
}
@Override
public String toString (String separator) {
return items.toString(separator);
}
static public class OrderedSetIterator<T> extends ObjectSetIterator<T> {
private Array<T> items;
public OrderedSetIterator (OrderedSet<T> set) {
super(set);
items = set.items;
}
@Override
public void reset () {
nextIndex = 0;
hasNext = set.size > 0;
}
@Override
public T next () {
if (!hasNext) throw new NoSuchElementException();
if (!valid) throw new RuntimeException("#iterator() cannot be used nested.");
T key = items.get(nextIndex);
nextIndex++;
hasNext = nextIndex < set.size;
return key;
}
@Override
public void remove () {
if (nextIndex < 0) throw new IllegalStateException("next must be called before remove.");
nextIndex--;
((OrderedSet)set).removeIndex(nextIndex);
}
}
}