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 006package fc.util; 007 008import java.util.*; 009 010/** 011Misc collection related utility methods. 012 013Inspired by similar on the web. 014*/ 015public final class C 016{ 017/** 018Create an return a list from the specified args. 019*/ 020public 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/** 034Create an return a Set from the specified args. 035*/ 036public 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/** 045Create an return a Map from the specified args, which are treated as key, value pairs in sequence. 046Example: 047<code> 048Map map = map("a", "hello", "b", 123, "c", new int[] {4,5,6}); 049</code> 050*/ 051 052public 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/** 066Create an return a Map from the specified args. 067Example: 068<code> 069Map map = map(e("a", "hello"), e("b", 123)); 070</code> 071*/ 072public 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/** 083Alias for the e method 084*/ 085public static Entry entry(final Object key, final Object val) 086 { 087 return new Entry(key, val); 088 } 089 090/** 091Create a map entry to pass to the map method. values can be null. The key, value 092pairs are accessed directly after they are put in the map. 093*/ 094public static Entry e(final Object key, final Object val) 095 { 096 return new Entry(key, val); 097 } 098 099private 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/** 111Pick NON-duplicate N random items from a list. If N < number of unique items in the list, throws 112a IllegalArgumentException. Also throws a IllegalArgumentException if not able to get unique 113items after 16 tries (per item). To specify a different retry count (per item), use the variant 114of this method that takes the retry parameter. 115 116@param count number (N) items to choose. 117*/ 118public static Set randomNNoDuplicates(final List list, final int count) throws IllegalArgumentException 119 { 120 return randomNNoDuplicates(list, count, 16); 121 } 122 123/** 124alias for the {@link #randomNNoDuplicates(List, int)} method 125*/ 126public static Set randomNNoDups(final List list, final int count) throws IllegalArgumentException 127 { 128 return randomNNoDuplicates(list, count, 16); 129 } 130 131/** 132Pick NON-duplicate N random items from a list. If N < number of unique items in the list, throws 133a IllegalArgumentException. Also throws a IllegalArgumentException if not able to get unique 134items 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*/ 139public 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 */ 173public static short unbox(Short s) { 174 if (s == null) return 0; 175 else return s; 176 } 177 178/** unbox and return 0 if null */ 179public static short unboxShort(Object s) { 180 return unbox((Short)s); 181 } 182 183/** unbox and return 0 if null */ 184public static int unbox(Integer i) { 185 if (i == null) return 0; 186 else return i; 187 } 188 189/** unbox and return 0 if null */ 190public static int unboxInt(Object i) { 191 return unbox((Integer)i); 192 } 193 194/** unbox and return 0 if null */ 195public static long unbox(Long l) { 196 if (l == null) return 0; 197 else return l; 198 } 199 200/** unbox and return 0 if null */ 201public static long unboxLong(Object i) { 202 return unbox((Long)i); 203 } 204 205/** unbox and return 0 if null */ 206public static double unbox(Double d) { 207 if (d == null) return 0; 208 else return d; 209 } 210 211/** unbox and return 0 if null */ 212public static double unboxDouble(Object d) { 213 return unbox((Double)d); 214 } 215 216/** unbox and return '0' if null */ 217public static char unbox(Character c) { 218 if (c == null) return '0'; 219 else return c; 220 } 221 222/** unbox and return '0' if null */ 223public static char unboxChar(Object c) { 224 return unbox((Character)c); 225 } 226 227/** unbox and return false if null */ 228public static boolean unbox(Boolean b) { 229 if (b == null) return false; 230 else return b; 231 } 232 233/** unbox and return false if null */ 234public static boolean unboxBool(Object b) { 235 return unbox((Boolean)b); 236 } 237 238/** unbox and return false if null */ 239public static boolean unboxBoolean(Object b) { 240 return unbox((Boolean)b); 241 } 242 243 244/** 245Returns true if the specified collection is null or empty. 246**/ 247public static boolean nullOrEmpty(Collection c) 248 { 249 return c != null && c.size() == 0; 250 } 251 252 253public 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