001package squidpony; 002 003import squidpony.squidmath.*; 004 005import java.util.*; 006 007/** 008 * Utility methods for more easily constructing data structures, particularly those in Java's standard library. 009 * All static methods and inner classes; meant to be imported with {@code import static squidpony.Maker.*}. 010 * Created by Tommy Ettinger on 5/19/2016. 011 */ 012public class Maker { 013 014 /** 015 * Stores any information relating to non-fatal issues, such as caught and handled Exceptions that still change the 016 * behavior of methods. Typically shouldn't be cleared while debugging, since it could be useful later on, and 017 * hopefully won't need to be written to in a release build. 018 */ 019 public static final StringBuilder issueLog = new StringBuilder(1024); 020 /** 021 * Makes a LinkedHashMap (LHM) with key and value types inferred from the types of k0 and v0, and considers all 022 * parameters key-value pairs, casting the Objects at positions 0, 2, 4... etc. to K and the objects at positions 023 * 1, 3, 5... etc. to V. If rest has an odd-number length, then it discards the last item. If any pair of items in 024 * rest cannot be cast to the correct type of K or V, then this inserts nothing for that pair and logs information 025 * on the problematic pair to the static Maker.issueLog field. 026 * @param k0 the first key; used to infer the types of other keys if generic parameters aren't specified. 027 * @param v0 the first value; used to infer the types of other values if generic parameters aren't specified. 028 * @param rest an array or vararg of keys and values in pairs; should contain alternating K, V, K, V... elements 029 * @param <K> the type of keys in the returned LinkedHashMap; if not specified, will be inferred from k0 030 * @param <V> the type of values in the returned LinkedHashMap; if not specified, will be inferred from v0 031 * @return a freshly-made LinkedHashMap with K keys and V values, using k0, v0, and the contents of rest to fill it 032 */ 033 @SuppressWarnings("unchecked") 034 public static <K, V> LinkedHashMap<K, V> makeLHM(K k0, V v0, Object... rest) 035 { 036 if(rest == null || rest.length == 0) 037 { 038 LinkedHashMap<K, V> lhm = new LinkedHashMap<>(2); 039 lhm.put(k0, v0); 040 return lhm; 041 } 042 LinkedHashMap<K, V> lhm = new LinkedHashMap<>(1 + (rest.length / 2)); 043 lhm.put(k0, v0); 044 045 for (int i = 0; i < rest.length - 1; i+=2) { 046 try { 047 lhm.put((K) rest[i], (V) rest[i + 1]); 048 }catch (ClassCastException cce) { 049 issueLog.append("makeLHM call had a casting problem with pair at rest[") 050 .append(i) 051 .append("] and/or rest[") 052 .append(i + 1) 053 .append("], with contents: ") 054 .append(rest[i]) 055 .append(", ") 056 .append(rest[i + 1]) 057 .append(".\n\nException messages:\n") 058 .append(cce); 059 String msg = cce.getMessage(); 060 if (msg != null) { 061 issueLog.append('\n').append(msg); 062 } 063 issueLog.append('\n'); 064 } 065 } 066 return lhm; 067 } 068 069 /** 070 * Makes an empty LinkedHashMap (LHM); needs key and value types to be specified in order to work. For an empty 071 * LinkedHashMap with String keys and Coord values, you could use {@code Maker.<String, Coord>makeLHM();}. Using 072 * the new keyword is probably just as easy in this case; this method is provided for completeness relative to 073 * makeLHM() with 2 or more parameters. 074 * @param <K> the type of keys in the returned LinkedHashMap; cannot be inferred and must be specified 075 * @param <V> the type of values in the returned LinkedHashMap; cannot be inferred and must be specified 076 * @return an empty LinkedHashMap with the given key and value types. 077 */ 078 public static <K, V> LinkedHashMap<K, V> makeLHM() 079 { 080 return new LinkedHashMap<>(); 081 } 082 /** 083 * Makes a HashMap (HM) with key and value types inferred from the types of k0 and v0, and considers all 084 * parameters key-value pairs, casting the Objects at positions 0, 2, 4... etc. to K and the objects at positions 085 * 1, 3, 5... etc. to V. If rest has an odd-number length, then it discards the last item. If any pair of items in 086 * rest cannot be cast to the correct type of K or V, then this inserts nothing for that pair and logs information 087 * on the problematic pair to the static Maker.issueLog field. 088 * @param k0 the first key; used to infer the types of other keys if generic parameters aren't specified. 089 * @param v0 the first value; used to infer the types of other values if generic parameters aren't specified. 090 * @param rest an array or vararg of keys and values in pairs; should contain alternating K, V, K, V... elements 091 * @param <K> the type of keys in the returned HashMap; if not specified, will be inferred from k0 092 * @param <V> the type of values in the returned HashMap; if not specified, will be inferred from v0 093 * @return a freshly-made HashMap with K keys and V values, using k0, v0, and the contents of rest to fill it 094 */ 095 @SuppressWarnings("unchecked") 096 public static <K, V> HashMap<K, V> makeHM(K k0, V v0, Object... rest) 097 { 098 if(rest == null || rest.length == 0) 099 { 100 HashMap<K, V> hm = new HashMap<>(2); 101 hm.put(k0, v0); 102 return hm; 103 } 104 HashMap<K, V> hm = new HashMap<>(1 + (rest.length / 2)); 105 hm.put(k0, v0); 106 107 for (int i = 0; i < rest.length - 1; i+=2) { 108 try { 109 hm.put((K) rest[i], (V) rest[i + 1]); 110 }catch (ClassCastException cce) { 111 issueLog.append("makeHM call had a casting problem with pair at rest[") 112 .append(i).append("] and/or rest[") 113 .append(i + 1).append("], with contents: ") 114 .append(rest[i]).append(", ") 115 .append(rest[i + 1]).append(".\n\nException messages:\n") 116 .append(cce); 117 String msg = cce.getMessage(); 118 if (msg != null) { 119 issueLog.append('\n').append(msg); 120 } 121 issueLog.append('\n'); 122 } 123 } 124 return hm; 125 } 126 127 /** 128 * Makes an empty HashMap (HM); needs key and value types to be specified in order to work. For an empty 129 * HashMap with String keys and Coord values, you could use {@code Maker.<String, Coord>makeHM();}. Using 130 * the new keyword is probably just as easy in this case; this method is provided for completeness relative to 131 * makeHM() with 2 or more parameters. 132 * @param <K> the type of keys in the returned HashMap; cannot be inferred and must be specified 133 * @param <V> the type of values in the returned HashMap; cannot be inferred and must be specified 134 * @return an empty HashMap with the given key and value types. 135 */ 136 public static <K, V> HashMap<K, V> makeHM() 137 { 138 return new HashMap<>(); 139 } 140 141 /** 142 * Makes an ArrayList of T given an array or vararg of T elements. 143 * @param elements an array or vararg of T 144 * @param <T> just about any non-primitive type 145 * @return a newly-allocated ArrayList containing all of elements, in order 146 */ 147 @SuppressWarnings("unchecked") 148 public static <T> ArrayList<T> makeList(T... elements) { 149 if(elements == null) return null; 150 ArrayList<T> list = new ArrayList<>(elements.length); 151 Collections.addAll(list, elements); 152 return list; 153 } 154 155 /** 156 * Makes an ArrayList of T given a single T element; avoids creating an array for varargs as 157 * {@link #makeList(Object[])} would do, but only allows one item. 158 * @param element an array or vararg of T 159 * @param <T> just about any non-primitive, non-array type (arrays would cause confusion with the vararg method) 160 * @return a newly-allocated ArrayList containing only element 161 */ 162 public static <T> ArrayList<T> makeList(T element) { 163 ArrayList<T> list = new ArrayList<>(1); 164 list.add(element); 165 return list; 166 } 167 168 /** 169 * Makes a LinkedHashSet (LHS) of T given an array or vararg of T elements. Duplicate items in elements will have 170 * all but one item discarded, using the later item in elements. 171 * @param elements an array or vararg of T 172 * @param <T> just about any non-primitive type 173 * @return a newly-allocated LinkedHashSet containing all of the non-duplicate items in elements, in order 174 */ 175 @SuppressWarnings("unchecked") 176 public static <T> LinkedHashSet<T> makeLHS(T... elements) { 177 if(elements == null) return null; 178 LinkedHashSet<T> set = new LinkedHashSet<>(elements.length); 179 Collections.addAll(set, elements); 180 return set; 181 } 182 183 /** 184 * Makes a LinkedHashSet (LHS) of T given a single T element. 185 * @param element a single T 186 * @param <T> just about any non-primitive type 187 * @return a newly-allocated LinkedHashSet containing only {@code element} 188 */ 189 public static <T> LinkedHashSet<T> makeLHS(T element) { 190 LinkedHashSet<T> set = new LinkedHashSet<T>(1); 191 set.add(element); 192 return set; 193 } 194 195 /** 196 * Makes a HashSet (HS) of T given an array or vararg of T elements. Duplicate items in elements will have 197 * all but one item discarded, using the later item in elements. 198 * @param elements an array or vararg of T 199 * @param <T> just about any non-primitive type 200 * @return a newly-allocated HashSet containing all of the non-duplicate items in elements, in order 201 */ 202 @SuppressWarnings("unchecked") 203 public static <T> HashSet<T> makeHS(T... elements) { 204 if(elements == null) return null; 205 HashSet<T> set = new HashSet<>(elements.length); 206 Collections.addAll(set, elements); 207 return set; 208 } 209 210 /** 211 * Makes a HashSet (HS) of T given a single T element. 212 * @param element a single T 213 * @param <T> just about any non-primitive type 214 * @return a newly-allocated HashSet containing only {@code element} 215 */ 216 public static <T> HashSet<T> makeHS(T element) { 217 HashSet<T> set = new HashSet<T>(1); 218 set.add(element); 219 return set; 220 } 221 222 /** 223 * Makes an OrderedMap (OM) with key and value types inferred from the types of k0 and v0, and considers all 224 * parameters key-value pairs, casting the Objects at positions 0, 2, 4... etc. to K and the objects at positions 225 * 1, 3, 5... etc. to V. If rest has an odd-number length, then it discards the last item. If any pair of items in 226 * rest cannot be cast to the correct type of K or V, then this inserts nothing for that pair and logs information 227 * on the problematic pair to the static Maker.issueLog field. 228 * @param k0 the first key; used to infer the types of other keys if generic parameters aren't specified. 229 * @param v0 the first value; used to infer the types of other values if generic parameters aren't specified. 230 * @param rest an array or vararg of keys and values in pairs; should contain alternating K, V, K, V... elements 231 * @param <K> the type of keys in the returned OrderedMap; if not specified, will be inferred from k0 232 * @param <V> the type of values in the returned OrderedMap; if not specified, will be inferred from v0 233 * @return a freshly-made OrderedMap with K keys and V values, using k0, v0, and the contents of rest to fill it 234 */ 235 public static <K, V> OrderedMap<K, V> makeOM(K k0, V v0, Object... rest) 236 { 237 return makeOM(0.625f, k0, v0, rest); 238 } 239 /** 240 * Makes an OrderedMap (OM) with the given load factor (which should be between 0.1 and 0.9), key and value types 241 * inferred from the types of k0 and v0, and considers all remaining parameters key-value pairs, casting the Objects 242 * at positions 0, 2, 4... etc. to K and the objects at positions 1, 3, 5... etc. to V. If rest has an odd-number 243 * length, then it discards the last item. If any pair of items in rest cannot be cast to the correct type of K or 244 * V, then this inserts nothing for that pair and logs information on the problematic pair to the static 245 * Maker.issueLog field. 246 * @param factor the load factor; should be between 0.1 and 0.9, and 0.75f is a safe choice 247 * @param k0 the first key; used to infer the types of other keys if generic parameters aren't specified. 248 * @param v0 the first value; used to infer the types of other values if generic parameters aren't specified. 249 * @param rest an array or vararg of keys and values in pairs; should contain alternating K, V, K, V... elements 250 * @param <K> the type of keys in the returned OrderedMap; if not specified, will be inferred from k0 251 * @param <V> the type of values in the returned OrderedMap; if not specified, will be inferred from v0 252 * @return a freshly-made OrderedMap with K keys and V values, using k0, v0, and the contents of rest to fill it 253 */ 254 @SuppressWarnings("unchecked") 255 public static <K, V> OrderedMap<K, V> makeOM(float factor, K k0, V v0, Object... rest) 256 { 257 if(rest == null || rest.length == 0) 258 { 259 OrderedMap<K, V> om = new OrderedMap<>(2, factor); 260 om.put(k0, v0); 261 return om; 262 } 263 OrderedMap<K, V> om = new OrderedMap<>(1 + (rest.length / 2), factor); 264 om.put(k0, v0); 265 266 for (int i = 0; i < rest.length - 1; i+=2) { 267 try { 268 om.put((K) rest[i], (V) rest[i + 1]); 269 }catch (ClassCastException cce) { 270 issueLog.append("makeOM call had a casting problem with pair at rest[") 271 .append(i) 272 .append("] and/or rest[") 273 .append(i + 1) 274 .append("], with contents: ") 275 .append(rest[i]) 276 .append(", ") 277 .append(rest[i+1]) 278 .append(".\n\nException messages:\n") 279 .append(cce); 280 String msg = cce.getMessage(); 281 if (msg != null) { 282 issueLog.append('\n').append(msg); 283 } 284 issueLog.append('\n'); 285 } 286 } 287 return om; 288 } 289 290 /** 291 * Makes an empty OrderedMap (OM); needs key and value types to be specified in order to work. For an empty 292 * OrderedMap with String keys and Coord values, you could use {@code Maker.<String, Coord>makeOM()}. Using 293 * the new keyword is probably just as easy in this case; this method is provided for completeness relative to 294 * makeOM() with 2 or more parameters. 295 * @param <K> the type of keys in the returned OrderedMap; cannot be inferred and must be specified 296 * @param <V> the type of values in the returned OrderedMap; cannot be inferred and must be specified 297 * @return an empty OrderedMap with the given key and value types. 298 */ 299 public static <K, V> OrderedMap<K, V> makeOM() 300 { 301 return new OrderedMap<>(); 302 } 303 304 /** 305 * Makes an OrderedSet (OS) of T given an array or vararg of T elements. Duplicate items in elements will have 306 * all but one item discarded, using the later item in elements. 307 * @param elements an array or vararg of T 308 * @param <T> just about any non-primitive type 309 * @return a newly-allocated OrderedSet containing all of the non-duplicate items in elements, in order 310 */ 311 @SuppressWarnings("unchecked") 312 public static <T> OrderedSet<T> makeOS(T... elements) { 313 if(elements == null) return null; 314 return new OrderedSet<>(elements); 315 } 316 317 /** 318 * Makes an OrderedSet of T given a single T element; avoids creating an array for varargs as 319 * {@link #makeOS(Object[])} would do, but only allows one item. 320 * @param element an array or vararg of T 321 * @param <T> just about any non-primitive, non-array type (arrays would cause confusion with the vararg method) 322 * @return a newly-allocated OrderedSet containing only element 323 */ 324 public static <T> OrderedSet<T> makeOS(T element) { 325 OrderedSet<T> set = new OrderedSet<>(1); 326 set.add(element); 327 return set; 328 } 329 330 /** 331 * Makes an UnorderedSet (UOS) of T given an array or vararg of T elements. Duplicate items in elements will have 332 * all but one item discarded, using the later item in elements; order will not be kept. 333 * @param elements an array or vararg of T 334 * @param <T> just about any non-primitive type 335 * @return a newly-allocated UnorderedSet containing all of the non-duplicate items in elements, in order 336 */ 337 @SuppressWarnings("unchecked") 338 public static <T> UnorderedSet<T> makeUOS(T... elements) { 339 if(elements == null) return null; 340 return new UnorderedSet<>(elements); 341 } 342 343 /** 344 * Makes an UnorderedSet of T given a single T element; avoids creating an array for varargs as 345 * {@link #makeOS(Object[])} would do, but only allows one item. 346 * @param element an array or vararg of T 347 * @param <T> just about any non-primitive, non-array type (arrays would cause confusion with the vararg method) 348 * @return a newly-allocated UnorderedSet containing only element 349 */ 350 public static <T> UnorderedSet<T> makeUOS(T element) { 351 UnorderedSet<T> set = new UnorderedSet<>(1); 352 set.add(element); 353 return set; 354 } 355 356 /** 357 * Makes a EnumOrderedSet (OS) of the enum type T given at least one T element followed by an array or vararg of any 358 * number of additional T elements. Duplicate items in elements will have all but one item discarded, using the 359 * later item in elements. The order given here will be kept in the result, like in OrderedSet, and 360 * you can use {@link EnumOrderedSet#getAt(int)} to get a T value at a given index, like you would with a List. 361 * @param initial the first item to insert into the EnumOrderedSet; if initial is null, the method returns null 362 * @param elements an array or vararg of T; allowed to be empty 363 * @param <T> an enum type 364 * @return a newly-allocated OrderedSet containing all of the non-duplicate items in elements, in order 365 */ 366 @SuppressWarnings("unchecked") 367 public static <T extends Enum<?>> EnumOrderedSet<T> makeEOS(T initial, T... elements) 368 { 369 if(initial == null) return null; 370 EnumOrderedSet<T> eos = new EnumOrderedSet<>(initial); 371 eos.add(initial); 372 if(elements != null) 373 eos.addAll(elements); 374 return eos; 375 } 376 377 /** 378 * Makes an empty EnumOrderedSet (EOS); needs item type to be specified in order to work. For an empty 379 * EnumOrderedSet with Radius items, you could use {@code Maker.<Radius>makeEOS()}. Using the new keyword is 380 * probably just as easy in this case; this method is provided for completeness relative to makeEOS() with 1 or more 381 * parameters. 382 * @param <T> the type of Enum keys in the returned EnumOrderedSet; cannot be inferred and must be specified 383 * @return an empty EnumOrderedSet with the given item type 384 */ 385 public static <T extends Enum<T>> EnumOrderedSet<T> makeEOS() { return new EnumOrderedSet<>(); } 386 387 /** 388 * Makes a Arrangement (Arrange) of T given an array or vararg of T elements. Duplicate items in elements will have 389 * all but one item discarded, using the later item in elements. As is always the case with Arrangement, each item 390 * will be mapped bi-directionally to its index in the iteration order, and an item can be retrieved with 391 * {@link Arrangement#keyAt(int)} if you only know its index, or the int index for an item can be retrieved with 392 * {@link Arrangement#getInt(Object)} if you only have an item. 393 * @param elements an array or vararg of T 394 * @param <T> just about any non-primitive type 395 * @return a newly-allocated Arrangement containing all of the non-duplicate items in elements, in order 396 */ 397 @SuppressWarnings("unchecked") 398 public static <T> Arrangement<T> makeArrange(T... elements) { 399 if(elements == null) return null; 400 return new Arrangement<>(elements); 401 } 402 /** 403 * Makes a K2 (two-key set/bimap) with A and B key types inferred from the types of a0 and b0, and considers all 404 * parameters A-B pairs, casting the Objects at positions 0, 2, 4... etc. to A and the objects at positions 405 * 1, 3, 5... etc. to B. If rest has an odd-number length, then it discards the last item. If any pair of items in 406 * rest cannot be cast to the correct type of A or B, then this inserts nothing for that pair and logs information 407 * on the problematic pair to the static Maker.issueLog field. 408 * @param a0 the first A key; used to infer the types of other keys if generic parameters aren't specified. 409 * @param b0 the first B key; used to infer the types of other values if generic parameters aren't specified. 410 * @param rest an array or vararg of keys and values in pairs; should contain alternating A, B, A, B... elements 411 * @param <A> a type of keys in the returned K2; if not specified, will be inferred from a0 412 * @param <B> a type of keys in the returned K2; if not specified, will be inferred from b0 413 * @return a freshly-made K2 with A and B keys, using a0, b0, and the contents of rest to fill it 414 */ 415 public static <A, B> K2<A, B> makeK2(A a0, B b0, Object... rest) 416 { 417 return makeK2(0.625f, a0, b0, rest); 418 } 419 /** 420 * Makes a K2 (two-key set/bimap) with the given load factor (which should be between 0.1 and 0.9), A and B key 421 * types inferred from the types of a0 and b0, and considers all parameters A-B pairs, casting the Objects at 422 * positions 0, 2, 4... etc. to A and the objects at positions 1, 3, 5... etc. to B. If rest has an odd-number 423 * length, then it discards the last item. If any pair of items in rest cannot be cast to the correct type of A or 424 * B, then this inserts nothing for that pair and logs information on the problematic pair to the static 425 * Maker.issueLog field. 426 * @param factor the load factor; should be between 0.1 and 0.9, and 0.75f is a safe choice 427 * @param a0 the first A key; used to infer the types of other keys if generic parameters aren't specified. 428 * @param b0 the first B key; used to infer the types of other values if generic parameters aren't specified. 429 * @param rest an array or vararg of keys and values in pairs; should contain alternating A, B, A, B... elements 430 * @param <A> a type of keys in the returned K2; if not specified, will be inferred from a0 431 * @param <B> a type of keys in the returned K2; if not specified, will be inferred from b0 432 * @return a freshly-made K2 with A and B keys, using a0, b0, and the contents of rest to fill it 433 */ 434 @SuppressWarnings("unchecked") 435 public static <A, B> K2<A, B> makeK2(float factor, A a0, B b0, Object... rest) 436 { 437 if(rest == null || rest.length == 0) 438 { 439 K2<A, B> k2 = new K2<>(2, factor); 440 k2.put(a0, b0); 441 return k2; 442 } 443 K2<A, B> k2 = new K2<>(1 + (rest.length >> 1), factor); 444 k2.put(a0, b0); 445 446 for (int i = 0; i < rest.length - 1; i+=2) { 447 try { 448 k2.put((A) rest[i], (B) rest[i + 1]); 449 }catch (ClassCastException cce) { 450 issueLog.append("makeK2 call had a casting problem with pair at rest[") 451 .append(i) 452 .append("] and/or rest[") 453 .append(i + 1) 454 .append("], with contents: ") 455 .append(rest[i]) 456 .append(", ") 457 .append(rest[i+1]) 458 .append(".\n\nException messages:\n") 459 .append(cce); 460 String msg = cce.getMessage(); 461 if (msg != null) { 462 issueLog.append('\n').append(msg); 463 } 464 issueLog.append('\n'); 465 } 466 } 467 return k2; 468 } 469 470 /** 471 * Makes an empty K2 (two-key set/bimap); needs A and B key types to be specified in order to work. For an empty 472 * K2 with String A keys Coord B keys, you could use {@code Maker.<String, Coord>makeK2();}. Using 473 * the new keyword is probably just as easy in this case; this method is provided for completeness relative to 474 * makeK2() with 2 or more parameters. 475 * @param <A> the type of "A" keys in the returned K2; cannot be inferred and must be specified 476 * @param <B> the type of "B" keys in the returned K2; cannot be inferred and must be specified 477 * @return an empty K2 with the given key and value types. 478 */ 479 public static <A, B> K2<A, B> makeK2() 480 { 481 return new K2<>(); 482 } 483 /** 484 * Makes an EnumOrderedMap (EOM) with key and value types inferred from the types of k0 and v0, and considers all 485 * remaining parameters key-value pairs, casting the Objects at positions 0, 2, 4... etc. to K and the objects at 486 * positions 1, 3, 5... etc. to V. If rest has an odd-number length, then it discards the last item. If any pair of 487 * items in rest cannot be cast to the correct type of K or V, then this inserts nothing for that pair and logs 488 * information on the problematic pair to the static Maker.issueLog field. The order given here will be kept in the 489 * result, unlike in the JDK's EnumMap class, and you can use {@link EnumOrderedMap#keyAt(int)} or 490 * {@link EnumOrderedMap#getAt(int)} to get a key or value at a given index, like you would with a List. 491 * 492 * @param k0 the first key, which must be an Enum; used to infer the types of other keys if generic parameters aren't specified. 493 * @param v0 the first value; used to infer the types of other values if generic parameters aren't specified. 494 * @param rest an array or vararg of keys and values in pairs; should contain alternating K, V, K, V... elements 495 * @param <K> the type of Enum keys in the returned EnumOrderedMap; if not specified, will be inferred from k0 496 * @param <V> the type of values in the returned EnumOrderedMap; if not specified, will be inferred from v0 497 * @return a freshly-made EnumOrderedMap with K keys and V values, using k0, v0, and the contents of rest to fill it 498 */ 499 @SuppressWarnings("unchecked") 500 public static <K extends Enum<?>, V> EnumOrderedMap<K, V> makeEOM(K k0, V v0, Object... rest) 501 { 502 if(rest == null || rest.length == 0) 503 { 504 EnumOrderedMap<K, V> eom = new EnumOrderedMap<>(); 505 eom.put(k0, v0); 506 return eom; 507 } 508 EnumOrderedMap<K, V> eom = new EnumOrderedMap<>(k0); 509 eom.put(k0, v0); 510 511 for (int i = 0; i < rest.length - 1; i+=2) { 512 try { 513 eom.put((K) rest[i], (V) rest[i + 1]); 514 }catch (ClassCastException cce) { 515 issueLog.append("makeEOM call had a casting problem with pair at rest[") 516 .append(i) 517 .append("] and/or rest[") 518 .append(i + 1) 519 .append("], with contents: ") 520 .append(rest[i]) 521 .append(", ") 522 .append(rest[i+1]) 523 .append(".\n\nException messages:\n") 524 .append(cce); 525 String msg = cce.getMessage(); 526 if (msg != null) { 527 issueLog.append('\n').append(msg); 528 } 529 issueLog.append('\n'); 530 } 531 } 532 return eom; 533 } 534 535 /** 536 * Makes an empty EnumOrderedMap (EOM); needs key and value types to be specified in order to work. For an empty 537 * EnumOrderedMap with Radius keys and Coord values, you could use {@code Maker.<Radius, Coord>makeEOM()}. Using 538 * the new keyword is probably just as easy in this case; this method is provided for completeness relative to 539 * makeEOM() with 2 or more parameters. 540 * @param <K> the type of Enum keys in the returned EnumOrderedMap; cannot be inferred and must be specified 541 * @param <V> the type of values in the returned EnumOrderedMap; cannot be inferred and must be specified 542 * @return an empty EnumOrderedMap with the given key and value types. 543 */ 544 public static <K extends Enum<K>, V> EnumOrderedMap<K, V> makeEOM() { return new EnumOrderedMap<>(); } 545 546}