001 // Copyright (c) 2001 Hursh Jain (http://www.mollypages.org)
002 // The Molly framework is freely distributable under the terms of an
003 // MIT-style license. For details, see the molly pages web site at:
004 // http://www.mollypages.org/. Use, modify, have fun !
005
006 package fc.util;
007
008 import java.util.*;
009
010 /**
011 Misc collection related utility methods.
012
013 Inspired by similar on the web.
014 */
015 public final class C
016 {
017 /**
018 Create an return a list from the specified args.
019 */
020 public static List list(final Object... args)
021 {
022 //Arrays.asList is a fixed sized list backed by Args, cannot add to it
023 //return Arrays.asList(args);
024
025 //return a proper list instead
026 final ArrayList list = new ArrayList(args.length);
027 for (int n = 0; n < args.length; n++) {
028 list.add(args[n]);
029 }
030 return list;
031 }
032
033 /**
034 Create an return a Set from the specified args.
035 */
036 public static Set set(final Object... args)
037 {
038 Set result = new HashSet(args.length);
039
040 result.addAll(Arrays.asList(args));
041 return result;
042 }
043
044 /**
045 Create an return a Map from the specified args, which are treated as key, value pairs in sequence.
046 Example:
047 <code>
048 Map map = map("a", "hello", "b", 123, "c", new int[] {4,5,6});
049 </code>
050 */
051
052 public static Map map(final Object...objects)
053 {
054 final Map result = new HashMap(objects.length/2);
055 if (objects.length % 2 == 1) {
056 throw new IllegalArgumentException("Need (key, value) pairs - number of args should be even!");
057 }
058 for (int n = 0; n < objects.length; n+=2)
059 {
060 result.put(objects[n], objects[n+1]);
061 }
062 return result;
063 }
064
065 /**
066 Create an return a Map from the specified args.
067 Example:
068 <code>
069 Map map = map(e("a", "hello"), e("b", 123));
070 </code>
071 */
072 public static Map map(final Entry... entries)
073 {
074 final Map result = new HashMap(entries.length);
075
076 for (Entry entry : entries) {
077 result.put(entry.key, entry.val);
078 }
079 return result;
080 }
081
082 /**
083 Alias for the e method
084 */
085 public static Entry entry(final Object key, final Object val)
086 {
087 return new Entry(key, val);
088 }
089
090 /**
091 Create a map entry to pass to the map method. values can be null. The key, value
092 pairs are accessed directly after they are put in the map.
093 */
094 public static Entry e(final Object key, final Object val)
095 {
096 return new Entry(key, val);
097 }
098
099 private static class Entry
100 {
101 Object key;
102 Object val;
103
104 public Entry(final Object key, final Object val) {
105 this.key = key;
106 this.val = val;
107 }
108 }
109
110 /**
111 Pick NON-duplicate N random items from a list. If N < number of unique items in the list, throws
112 a IllegalArgumentException. Also throws a IllegalArgumentException if not able to get unique
113 items after 16 tries (per item). To specify a different retry count (per item), use the variant
114 of this method that takes the retry parameter.
115
116 @param count number (N) items to choose.
117 */
118 public static Set randomNNoDuplicates(final List list, final int count) throws IllegalArgumentException
119 {
120 return randomNNoDuplicates(list, count, 16);
121 }
122
123 /**
124 alias for the {@link #randomNNoDuplicates(List, int)} method
125 */
126 public static Set randomNNoDups(final List list, final int count) throws IllegalArgumentException
127 {
128 return randomNNoDuplicates(list, count, 16);
129 }
130
131 /**
132 Pick NON-duplicate N random items from a list. If N < number of unique items in the list, throws
133 a IllegalArgumentException. Also throws a IllegalArgumentException if not able to get unique
134 items after the specified (per item).
135
136 @param count number (N) items to choose.
137 @param retries number of retries to get a unique random item before bailing/throwing an Exception
138 */
139 public static Set randomNNoDuplicates(final List list, final int count, final int retries) throws IllegalArgumentException
140 {
141 if (list.size() < count) {
142 throw new IllegalArgumentException("The specified list does not contain [" + count + "] items");
143 }
144
145 final Set set = new HashSet();
146 set.addAll(list);
147
148 //these many unique items exist ?
149 if (set.size() < count) {
150 throw new IllegalArgumentException("The specified list does not contain [" + count + "] unique items");
151 }
152 set.clear();
153 Random r = new Random();
154
155 for (int n = 0; n < count; n++)
156 {
157 Object item = list.get(r.nextInt(list.size()));
158 int tries = 0;
159 while (set.contains(item))
160 {
161 item = list.get(r.nextInt(list.size()));
162 tries++;
163 if (tries > retries) {
164 throw new IllegalArgumentException("Too many tries to get a unique item");
165 }
166 }
167 set.add(item);
168 }
169 return set;
170 }
171
172 /** unbox and return 0 if null */
173 public static short unbox(Short s) {
174 if (s == null) return 0;
175 else return s;
176 }
177
178 /** unbox and return 0 if null */
179 public static short unboxShort(Object s) {
180 return unbox((Short)s);
181 }
182
183 /** unbox and return 0 if null */
184 public static int unbox(Integer i) {
185 if (i == null) return 0;
186 else return i;
187 }
188
189 /** unbox and return 0 if null */
190 public static int unboxInt(Object i) {
191 return unbox((Integer)i);
192 }
193
194 /** unbox and return 0 if null */
195 public static long unbox(Long l) {
196 if (l == null) return 0;
197 else return l;
198 }
199
200 /** unbox and return 0 if null */
201 public static long unboxLong(Object i) {
202 return unbox((Long)i);
203 }
204
205 /** unbox and return 0 if null */
206 public static double unbox(Double d) {
207 if (d == null) return 0;
208 else return d;
209 }
210
211 /** unbox and return 0 if null */
212 public static double unboxDouble(Object d) {
213 return unbox((Double)d);
214 }
215
216 /** unbox and return '0' if null */
217 public static char unbox(Character c) {
218 if (c == null) return '0';
219 else return c;
220 }
221
222 /** unbox and return '0' if null */
223 public static char unboxChar(Object c) {
224 return unbox((Character)c);
225 }
226
227 /** unbox and return false if null */
228 public static boolean unbox(Boolean b) {
229 if (b == null) return false;
230 else return b;
231 }
232
233 /** unbox and return false if null */
234 public static boolean unboxBool(Object b) {
235 return unbox((Boolean)b);
236 }
237
238 /** unbox and return false if null */
239 public static boolean unboxBoolean(Object b) {
240 return unbox((Boolean)b);
241 }
242
243
244 /**
245 Returns true if the specified collection is null or empty.
246 **/
247 public static boolean nullOrEmpty(Collection c)
248 {
249 return c != null && c.size() == 0;
250 }
251
252
253 public static void main(String args[])
254 {
255 List list = list("a", "b", 1);
256 System.out.println(list);
257
258 Set set = set("a", "b", "b", "c", 1);
259 System.out.println(set);
260
261 Map map = map(entry("a", 123), entry("b", new Object()), e(1, "1"), e(2, null));
262 System.out.println(map);
263
264 Map map2 = map("a", "hello", "b", 123, "c", new int[] {4,5,6}, "s", null);
265 System.out.println(map2);
266
267 //traditional way
268 String s = (String) map2.get("s");
269 System.out.println("string:" + s);
270
271 //unbox util
272 int i = unboxInt(map2.get("b"));
273 System.out.println("int:" + i);
274
275 //any null value can be unboxed at any type
276 int i2 = unboxInt(map2.get("s"));
277 System.out.println("int:" + i2);
278
279 //any null value can be unboxed at any type
280 boolean b = unboxBool(map2.get("s"));
281 System.out.println("boolean: " + b);
282
283 List list2 = list("a", "b", "a", "c", "d", "c", "g");
284 System.out.println(randomNNoDuplicates(list2, 3));
285
286 System.out.println("==Exception expected===");
287 try {
288 list2 = list("a", "b");
289 System.out.println(randomNNoDuplicates(list2, 3));
290 }
291 catch (Exception e) {
292 System.out.println(e);
293 }
294 System.out.println("==end Exception expected===");
295
296 list2 = list("a", "b", "c");
297 System.out.println(randomNNoDuplicates(list2, 3));
298
299 for (int n = 0; n < 300; n++) {
300 list2.add("x");
301 }
302
303 Collections.shuffle(list2);
304
305 System.out.println("==should more than likely throw a retry count exception==");
306 try {
307 System.out.println(randomNNoDuplicates(list2, 3));
308 }
309 catch (Exception e) {
310 System.out.println(e);
311 }
312
313 System.out.println("==should more than likely NOT throw a retry count exception (trying 1000 times per item) ==");
314 System.out.println(randomNNoDuplicates(list2, 3, 1000));
315 }
316 }
317