SortedBag.java revision 7935b1839a081ed19ae0d33029ad3c09632a2caa
1/* 2********************************************************************** 3* Copyright (c) 2002-2012, International Business Machines 4* Corporation and others. All Rights Reserved. 5********************************************************************** 6* Author: Mark Davis 7********************************************************************** 8*/package com.ibm.icu.dev.util; 9 10import java.util.Collection; 11import java.util.Comparator; 12import java.util.HashSet; 13import java.util.Iterator; 14import java.util.Map; 15import java.util.Set; 16import java.util.TreeMap; 17 18/** 19 * A collection that is like a sorted set, except that it allows 20 * multiple elements that compare as equal 21 * @author medavis 22 */ 23// TODO replace use of Set with a collection that takes an Equator 24public class SortedBag implements Collection { 25 /** 26 * A map of sets, where each corresponds to one sorted element. 27 * The sets are never empty 28 */ 29 private Map m; 30 private int size; 31 32 public SortedBag(Comparator c) { 33 m = new TreeMap(c); 34 } 35 public boolean add(Object s) { 36 Set o = (Set)m.get(s); 37 if (o == null) { 38 o = new HashSet(1); 39 m.put(s,o); 40 } 41 boolean result = o.add(s); 42 if (result) size++; 43 return result; 44 } 45 public Iterator iterator() { 46 return new MyIterator(); 47 } 48 static Iterator EMPTY_ITERATOR = new HashSet().iterator(); 49 private class MyIterator implements Iterator { 50 private Iterator mapIterator = m.keySet().iterator(); 51 private Iterator setIterator = null; 52 53 private MyIterator() { 54 mapIterator = m.keySet().iterator(); 55 setIterator = getSetIterator(); 56 } 57 private Iterator getSetIterator() { 58 if (!mapIterator.hasNext()) return EMPTY_ITERATOR; 59 return ((Set)m.get(mapIterator.next())).iterator(); 60 } 61 public boolean hasNext() { 62 return setIterator.hasNext() || mapIterator.hasNext(); 63 } 64 public Object next() { 65 if (!setIterator.hasNext()) { 66 setIterator = getSetIterator(); 67 } 68 return setIterator.next(); 69 } 70 public void remove() { 71 throw new UnsupportedOperationException(); 72 } 73 } 74 /** 75 * 76 */ 77 public void clear() { 78 m.clear(); 79 } 80 public int size() { 81 return size; 82 } 83 public boolean isEmpty() { 84 return size == 0; 85 } 86 public boolean contains(Object o) { 87 Set set = (Set)m.get(o); 88 if (set == null) return false; 89 return set.contains(o); 90 } 91 public Object[] toArray() { 92 return toArray(new Object[size]); 93 } 94 public Object[] toArray(Object[] a) { 95 int count = 0; 96 for (Iterator it = iterator(); it.hasNext();) { 97 a[count++] = it.next(); 98 } 99 return a; 100 } 101 /* (non-Javadoc) 102 * @see java.util.Collection#remove(java.lang.Object) 103 */ 104 public boolean remove(Object o) { 105 Set set = (Set)m.get(o); 106 if (set == null) return false; 107 if (!set.remove(o)) return false; 108 if (set.size() == 0) m.remove(o); 109 size--; 110 return true; 111 } 112 public boolean containsAll(Collection c) { 113 for (Iterator it = c.iterator(); it.hasNext(); ) { 114 if (!contains(it.next())) return false; 115 } 116 return true; 117 } 118 public boolean addAll(Collection c) { 119 boolean result = false; 120 for (Iterator it = c.iterator(); it.hasNext(); ) { 121 if (add(it.next())) result = true; 122 } 123 return result; 124 } 125 public boolean removeAll(Collection c) { 126 boolean result = false; 127 for (Iterator it = c.iterator(); it.hasNext(); ) { 128 if (remove(it.next())) result = true; 129 } 130 return result; 131 } 132 public boolean retainAll(Collection c) { 133 // WARNING: this may not work if the comparator does not distinguish 134 // all items that are equals(). 135 Set stuffToRemove = new HashSet(); // have to do this since iterator may not allow removal! 136 for (Iterator it = iterator(); it.hasNext(); ) { 137 Object item = it.next(); 138 if (!c.contains(item)) stuffToRemove.add(item); 139 } 140 return removeAll(stuffToRemove); 141 } 142} 143