001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
003: * for visualizing and manipulating spatial features with geometry and attributes.
004: *
005: * Copyright (C) 2003 Vivid Solutions
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: *
021: * For more information, contact:
022: *
023: * Vivid Solutions
024: * Suite #1A
025: * 2328 Government Street
026: * Victoria BC V8T 5G5
027: * Canada
028: *
029: * (250)385-6040
030: * www.vividsolutions.com
031: */
032: package com.vividsolutions.jump.util;
033:
034: import com.vividsolutions.jts.util.Assert;
035:
036: import java.util.ArrayList;
037: import java.util.Collection;
038: import java.util.Collections;
039: import java.util.HashMap;
040: import java.util.Iterator;
041: import java.util.List;
042: import java.util.Map;
043: import java.util.SortedSet;
044: import java.util.TreeSet;
045:
046: public class CollectionUtil {
047: public CollectionUtil() {
048: }
049:
050: public static Collection concatenate(Collection a, Collection b) {
051: ArrayList result = new ArrayList();
052: result.addAll(a);
053: result.addAll(b);
054: return result;
055: }
056:
057: public static List list(Object a, Object b) {
058: ArrayList list = new ArrayList();
059: list.add(a);
060: list.add(b);
061: return list;
062: }
063:
064: /**
065: * Returns a List of Lists: all combinations of the elements of the given List.
066: * @param maxCombinationSize combinations larger than this value are discarded
067: */
068: public static List combinations(List original,
069: int maxCombinationSize) {
070: return combinations(original, maxCombinationSize, null);
071: }
072:
073: public static Map inverse(Map map) {
074: Map inverse;
075: try {
076: inverse = (Map) map.getClass().newInstance();
077: } catch (InstantiationException e) {
078: Assert.shouldNeverReachHere(e.toString());
079:
080: return null;
081: } catch (IllegalAccessException e) {
082: Assert.shouldNeverReachHere(e.toString());
083:
084: return null;
085: }
086: for (Iterator i = map.keySet().iterator(); i.hasNext();) {
087: Object key = i.next();
088: Object value = map.get(key);
089: inverse.put(value, key);
090: }
091:
092: return inverse;
093: }
094:
095: /**
096: * Returns a List of Lists: all combinations of the elements of the given List.
097: * @param maxCombinationSize combinations larger than this value are discarded
098: * @param mandatoryItem an item that all returned combinations must contain,
099: * or null to leave unspecified
100: */
101: public static List combinations(List original,
102: int maxCombinationSize, Object mandatoryItem) {
103: ArrayList combinations = new ArrayList();
104:
105: //Combinations are given by the bits of each binary number from 1 to 2^N
106: for (int i = 1; i <= ((int) Math.pow(2, original.size()) - 1); i++) {
107: ArrayList combination = new ArrayList();
108: for (int j = 0; j < original.size(); j++) {
109: if ((i & (int) Math.pow(2, j)) > 0) {
110: combination.add(original.get(j));
111: }
112: }
113: if (combination.size() > maxCombinationSize) {
114: continue;
115: }
116: if ((mandatoryItem != null)
117: && !combination.contains(mandatoryItem)) {
118: continue;
119: }
120: combinations.add(combination);
121: }
122:
123: return combinations;
124: }
125:
126: /**
127: * Returns a List of Lists: all combinations of the elements of the given List.
128: */
129: public static List combinations(List original) {
130: return combinations(original, original.size(), null);
131: }
132:
133: public static void removeKeys(Collection keys, Map map) {
134: for (Iterator i = keys.iterator(); i.hasNext();) {
135: Object key = (Object) i.next();
136: map.remove(key);
137: }
138: }
139:
140: /**
141: * The nth key corresponds to the nth value
142: */
143: public static List[] keysAndCorrespondingValues(Map map) {
144: ArrayList keys = new ArrayList(map.keySet());
145: ArrayList values = new ArrayList();
146: for (Iterator i = keys.iterator(); i.hasNext();) {
147: Object key = i.next();
148: values.add(map.get(key));
149: }
150:
151: return new List[] { keys, values };
152: }
153:
154: public static Collection concatenate(Collection collections) {
155: ArrayList concatenation = new ArrayList();
156: for (Iterator i = collections.iterator(); i.hasNext();) {
157: Collection collection = (Collection) i.next();
158: concatenation.addAll(collection);
159: }
160:
161: return concatenation;
162: }
163:
164: public static Object randomElement(List list) {
165: return list.get((int) Math.floor(Math.random() * list.size()));
166: }
167:
168: public static SortedSet reverseSortedSet(int[] ints) {
169: TreeSet sortedSet = new TreeSet(Collections.reverseOrder());
170: for (int i = 0; i < ints.length; i++) {
171: sortedSet.add(new Integer(ints[i]));
172: }
173:
174: return sortedSet;
175: }
176:
177: public static List reverse(List list) {
178: Collections.reverse(list);
179:
180: return list;
181: }
182:
183: /**
184: * Data is evenly discarded or duplicated to attain the new size
185: */
186: public static Collection stretch(Collection source,
187: Collection destination, int destinationSize) {
188: Assert.isTrue(destination.isEmpty());
189:
190: List originalList = source instanceof List ? (List) source
191: : new ArrayList(source);
192: for (int i = 0; i < destinationSize; i++) {
193: destination.add(originalList.get((int) Math.round(i
194: * originalList.size() / (double) destinationSize)));
195: }
196:
197: return destination;
198: }
199:
200: public static Object ifNotIn(Object o, Collection c,
201: Object alternative) {
202: return c.contains(o) ? o : alternative;
203: }
204:
205: public static void setIfNull(int i, List list, String value) {
206: if (i >= list.size()) {
207: resize(list, i + 1);
208: }
209: if (list.get(i) != null) {
210: return;
211: }
212: list.set(i, value);
213: }
214:
215: public static void resize(List list, int newSize) {
216: if (newSize < list.size()) {
217: list.subList(newSize, list.size()).clear();
218: } else {
219: list.addAll(Collections
220: .nCopies(newSize - list.size(), null));
221: }
222: }
223:
224: public static boolean containsReference(Object[] objects, Object o) {
225: return indexOf(o, objects) > -1;
226: }
227:
228: public static int indexOf(Object o, Object[] objects) {
229: for (int i = 0; i < objects.length; i++) {
230: if (objects[i] == o) {
231: return i;
232: }
233: }
234:
235: return -1;
236: }
237:
238: /**
239: * Brute force, for when HashSet and TreeSet won't work (e.g. #hashCode
240: * implementation isn't appropriate). The original Collection is not modified.
241: */
242: public static Collection removeDuplicates(Collection original) {
243: ArrayList result = new ArrayList();
244: for (Iterator i = original.iterator(); i.hasNext();) {
245: Object item = i.next();
246: if (!result.contains(item)) {
247: result.add(item);
248: }
249: }
250:
251: return result;
252: }
253:
254: public static void addIfNotNull(Object item, Collection collection) {
255: if (item != null) {
256: collection.add(item);
257: }
258: }
259:
260: /**
261: * Modifies and returns the collection.
262: */
263: public static Collection filterByClass(Collection collection,
264: Class c) {
265: for (Iterator i = collection.iterator(); i.hasNext();) {
266: Object item = i.next();
267: if (!c.isInstance(item)) {
268: i.remove();
269: }
270: }
271:
272: return collection;
273: }
274:
275: public static Map createMap(Object[] alternatingKeysAndValues) {
276: return createMap(HashMap.class, alternatingKeysAndValues);
277: }
278:
279: public static Map createMap(Class mapClass,
280: Object[] alternatingKeysAndValues) {
281: Map map = null;
282: try {
283: map = (Map) mapClass.newInstance();
284: } catch (Exception e) {
285: Assert.shouldNeverReachHere(e.toString());
286: }
287: for (int i = 0; i < alternatingKeysAndValues.length; i += 2) {
288: map.put(alternatingKeysAndValues[i],
289: alternatingKeysAndValues[i + 1]);
290: }
291:
292: return map;
293: }
294:
295: /**
296: * The Smalltalk #collect method.
297: */
298: public static Collection collect(Collection collection, Block block) {
299: ArrayList result = new ArrayList();
300: for (Iterator i = collection.iterator(); i.hasNext();) {
301: Object item = i.next();
302: result.add(block.yield(item));
303: }
304:
305: return result;
306: }
307:
308: /**
309: * The Smalltalk #select method.
310: */
311: public static Collection select(Collection collection, Block block) {
312: ArrayList result = new ArrayList();
313: for (Iterator i = collection.iterator(); i.hasNext();) {
314: Object item = i.next();
315: if (Boolean.TRUE.equals(block.yield(item))) {
316: result.add(item);
317: }
318: ;
319: }
320:
321: return result;
322: }
323:
324: public static Object get(Class c, Map map) {
325: if (map.keySet().contains(c)) {
326: return map.get(c);
327: }
328: for (Iterator i = map.keySet().iterator(); i.hasNext();) {
329: Class candidateClass = (Class) i.next();
330: if (candidateClass.isAssignableFrom(c)) {
331: return map.get(candidateClass);
332: }
333: }
334:
335: return null;
336: }
337: }
|