Skip to main content
summaryrefslogtreecommitdiffstats
blob: 0cecf9718cff458aae151d19ad7fe67997753a09 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/*******************************************************************************
 * Copyright (c) 2005, 2010 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0, which accompanies this distribution
 * and is available at http://www.eclipse.org/legal/epl-v10.html.
 * 
 * Contributors:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.common.utility.internal;

import java.io.Serializable;
import java.util.AbstractCollection;
import java.util.Iterator;
import org.eclipse.jpt.common.utility.internal.iterators.EmptyIterator;

/**
 * A collection that allows duplicate elements.
 * <p>
 * The <code>Bag</code> interface places additional stipulations,
 * beyond those inherited from the {@link java.util.Collection} interface,
 * on the contracts of the {@link #equals(Object)} and {@link #hashCode()} methods.
 * 
 * @see HashBag
 */

public interface Bag<E> extends java.util.Collection<E> {

	/**
	 * Compares the specified object with this bag for equality. Returns
	 * <code>true</code> if the specified object is also a bag, the two bags
	 * have the same size, and every member of the specified bag is
	 * contained in this bag with the same number of occurrences (or equivalently,
	 * every member of this bag is contained in the specified bag with the same
	 * number of occurrences). This definition ensures that the
	 * equals method works properly across different implementations of the
	 * bag interface.
	 */
	boolean equals(Object o);

	/**
	 * Returns the hash code value for this bag. The hash code of a bag is
	 * defined to be the sum of the hash codes of the elements in the bag,
	 * where the hashcode of a <code>null</code> element is defined to be zero.
	 * This ensures that <code>b1.equals(b2)</code> implies that
	 * <code>b1.hashCode() == b2.hashCode()</code> for any two bags
	 * <code>b1</code> and <code>b2</code>, as required by the general
	 * contract of the {@link Object#hashCode()} method.
	 */
	int hashCode();

	/**
	 * Return the number of times the specified object occurs in the bag.
	 */
	int count(Object o);

	/**
	 * Add the specified object the specified number of times to the bag.
	 * Return whether the bag changed.
	 */
	boolean add(E o, int count);

	/**
	 * Remove the specified number of occurrences of the specified object
	 * from the bag. Return whether the bag changed.
	 */
	boolean remove(Object o, int count);

	/**
	 * Return an iterator that returns each item in the bag
	 * once and only once, irrespective of how many times
	 * the item was added to the bag.
	 */
	java.util.Iterator<E> uniqueIterator();

	/**
	 * Return the number of unique items in the bag.
	 */
	int uniqueCount();

	/**
	 * Return an iterator that returns an entry for each item in the bag
	 * once and only once, irrespective of how many times
	 * the item was added to the bag. The entry will indicate the item's
	 * count.
	 */
	java.util.Iterator<Entry<E>> entries();


	/**
	 * A bag entry (element-count pair).
	 * The {@link Bag#entries()} method returns an iterator whose
	 * elements are of this class. The <em>only</em> way to obtain a reference
	 * to a bag entry is from the iterator returned by this method. These
	 * <code>Bag.Entry</code> objects are valid <em>only</em> for the duration
	 * of the iteration; more formally, the behavior of a bag entry is
	 * undefined if the backing bag has been modified after the entry was
	 * returned by the iterator, except through the {@link #setCount(int)}
	 * operation on the bag entry.
	 */
	interface Entry<E> {

		/**
		 * Return the entry's element.
		 */
		E getElement();

		/**
		 * Return entry's count; i.e. the number of times the entry's element
		 * occurs in the bag.
		 * @see Bag#count(Object)
		 */
		int getCount();

		/**
		 * Set the entry's count; i.e. the number of times the entry's element
		 * occurs in the bag. The new count must be a positive number.
		 * Return the previous count of the entry's element.
		 * NB: Use {@link Iterator#remove()} to set the
		 * count to zero.
		 */
		int setCount(int count);

		/**
		 * Return whether the entry is equal to the specified object;
		 * i.e. the specified object is a <code>Bag.Entry</code> and its
		 * element and count are the same as the entry's.
		 */
		boolean equals(Object obj);

		/**
		 * Return the entry's hash code.
		 */
		int hashCode();

	}


	final class Empty<E> extends AbstractCollection<E> implements Bag<E>, Serializable {
		@SuppressWarnings("rawtypes")
		public static final Bag INSTANCE = new Empty();
		@SuppressWarnings("unchecked")
		public static <T> Bag<T> instance() {
			return INSTANCE;
		}
		// ensure single instance
		private Empty() {
			super();
		}
		@Override
		public Iterator<E> iterator() {
			return EmptyIterator.instance();
		}
		@Override
		public int size() {
			return 0;
		}
		public Iterator<E> uniqueIterator() {
			return EmptyIterator.instance();
		}
		public int uniqueCount() {
			return 0;
		}
		public int count(Object o) {
			return 0;
		}
		public Iterator<Bag.Entry<E>> entries() {
			return EmptyIterator.instance();
		}
		public boolean remove(Object o, int count) {
			return false;
		}
		public boolean add(E o, int count) {
			throw new UnsupportedOperationException();
		}
		@Override
		public boolean equals(Object o) {
			if (o == this) {
				return true;
			}
			if ( ! (o instanceof Bag<?>)) {
				return false;
			}
			return ((Bag<?>) o).size() == 0;
		}
		@Override
		public int hashCode() {
			return 0;
		}
		private static final long serialVersionUID = 1L;
		private Object readResolve() {
			// replace this object with the singleton
			return INSTANCE;
		}
	}

}

Back to the top