blob: 170e7148ce2daa1cb94d188d91b63c34efd6e691 [file] [log] [blame]
/*
**********************************************************************
* Copyright (c) 2002-2006, International Business Machines
* Corporation and others. All Rights Reserved.
**********************************************************************
* Author: Mark Davis
**********************************************************************
*/package com.ibm.icu.dev.test.util;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
/**
* A collection that is like a sorted set, except that it allows
* multiple elements that compare as equal
* @author medavis
*/
// TODO replace use of Set with a collection that takes an Equator
public class SortedBag implements Collection {
/**
* A map of sets, where each corresponds to one sorted element.
* The sets are never empty
*/
private Map m;
private int size;
public SortedBag(Comparator c) {
m = new TreeMap(c);
}
public boolean add(Object s) {
Set o = (Set)m.get(s);
if (o == null) {
o = new HashSet(1);
m.put(s,o);
}
boolean result = o.add(s);
if (result) size++;
return result;
}
public Iterator iterator() {
return new MyIterator();
}
static Iterator EMPTY_ITERATOR = new HashSet().iterator();
private class MyIterator implements Iterator {
private Iterator mapIterator = m.keySet().iterator();
private Iterator setIterator = null;
private MyIterator() {
mapIterator = m.keySet().iterator();
setIterator = getSetIterator();
}
private Iterator getSetIterator() {
if (!mapIterator.hasNext()) return EMPTY_ITERATOR;
return ((Set)m.get(mapIterator.next())).iterator();
}
public boolean hasNext() {
return setIterator.hasNext() || mapIterator.hasNext();
}
public Object next() {
if (!setIterator.hasNext()) {
setIterator = getSetIterator();
}
return setIterator.next();
}
public void remove() {
throw new UnsupportedOperationException();
}
}
/**
*
*/
public void clear() {
m.clear();
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public boolean contains(Object o) {
Set set = (Set)m.get(o);
if (set == null) return false;
return set.contains(o);
}
public Object[] toArray() {
return toArray(new Object[size]);
}
public Object[] toArray(Object[] a) {
int count = 0;
for (Iterator it = iterator(); it.hasNext();) {
a[count++] = it.next();
}
return a;
}
/* (non-Javadoc)
* @see java.util.Collection#remove(java.lang.Object)
*/
public boolean remove(Object o) {
Set set = (Set)m.get(o);
if (set == null) return false;
if (!set.remove(o)) return false;
if (set.size() == 0) m.remove(o);
size--;
return true;
}
public boolean containsAll(Collection c) {
for (Iterator it = c.iterator(); it.hasNext(); ) {
if (!contains(it.next())) return false;
}
return true;
}
public boolean addAll(Collection c) {
boolean result = false;
for (Iterator it = c.iterator(); it.hasNext(); ) {
if (add(it.next())) result = true;
}
return result;
}
public boolean removeAll(Collection c) {
boolean result = false;
for (Iterator it = c.iterator(); it.hasNext(); ) {
if (remove(it.next())) result = true;
}
return result;
}
public boolean retainAll(Collection c) {
// WARNING: this may not work if the comparator does not distinguish
// all items that are equals().
Set stuffToRemove = new HashSet(); // have to do this since iterator may not allow removal!
for (Iterator it = iterator(); it.hasNext(); ) {
Object item = it.next();
if (!c.contains(item)) stuffToRemove.add(item);
}
return removeAll(stuffToRemove);
}
}