/revolsys-core/src/main/java/com/revolsys/collection/map/Maps.java

https://github.com/revolsys/com.revolsys.open · Java · 982 lines · 848 code · 107 blank · 27 comment · 217 complexity · 3f688f868f675e352470e3e63176ee56 MD5 · raw file

  1. package com.revolsys.collection.map;
  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. import java.util.Collections;
  5. import java.util.Comparator;
  6. import java.util.HashMap;
  7. import java.util.LinkedHashMap;
  8. import java.util.LinkedHashSet;
  9. import java.util.List;
  10. import java.util.Map;
  11. import java.util.Map.Entry;
  12. import java.util.Properties;
  13. import java.util.Set;
  14. import java.util.TreeMap;
  15. import java.util.TreeSet;
  16. import java.util.function.Function;
  17. import java.util.function.Supplier;
  18. import java.util.prefs.BackingStoreException;
  19. import java.util.prefs.Preferences;
  20. import org.jeometry.common.data.type.DataType;
  21. import org.jeometry.common.data.type.DataTypes;
  22. import com.revolsys.record.io.format.json.JsonObject;
  23. import com.revolsys.util.BaseCloneable;
  24. import com.revolsys.util.Property;
  25. public interface Maps {
  26. public static final Supplier<Map<?, ?>> FACTORY_TREE = () -> {
  27. return new TreeMap<>();
  28. };
  29. public static final Supplier<Map<?, ?>> FACTORY_LINKED_HASH = () -> {
  30. return new LinkedHashMap<>();
  31. };
  32. public static final Supplier<Map<?, ?>> FACTORY_HASH = () -> {
  33. return new HashMap<>();
  34. };
  35. static <K1, V> boolean addAllToSet(final Map<K1, Set<V>> map, final K1 key1,
  36. final Collection<? extends V> values) {
  37. if (Property.hasValue(values)) {
  38. final Set<V> set = getSet(map, key1);
  39. return set.addAll(values);
  40. } else {
  41. return true;
  42. }
  43. }
  44. static <K> Integer addCount(final Map<K, Integer> counts, final K key) {
  45. Integer count = counts.get(key);
  46. if (count == null) {
  47. count = 1;
  48. } else {
  49. count++;
  50. }
  51. counts.put(key, count);
  52. return count;
  53. }
  54. static <K, V, C extends Collection<V>> boolean addToCollection(final Supplier<C> supplier,
  55. final Map<K, C> map, final K key, final V value) {
  56. final C values = get(map, key, supplier);
  57. return values.add(value);
  58. }
  59. static <K1, K2, C extends Collection<V>, V> boolean addToCollection(final Supplier<C> factory,
  60. final Map<K1, Map<K2, C>> map, final K1 key1, final K2 key2, final V value) {
  61. final C values = getCollection(factory, map, key1, key2);
  62. return values.add(value);
  63. }
  64. static <K1, V> boolean addToList(final Map<K1, List<V>> map, final K1 key1, final V value) {
  65. if (map != null && key1 != null) {
  66. final List<V> values = getList(map, key1);
  67. return values.add(value);
  68. } else {
  69. return false;
  70. }
  71. }
  72. static <K1, K2, V> boolean addToList(final Map<K1, Map<K2, List<V>>> map, final K1 key1,
  73. final K2 key2, final V value) {
  74. final List<V> values = getList(map, key1, key2);
  75. return values.add(value);
  76. }
  77. static <K1, K2, V> boolean addToList(final Supplier<Map<K2, List<V>>> supplier,
  78. final Map<K1, Map<K2, List<V>>> map, final K1 key1, final K2 key2, final V value) {
  79. final List<V> values = getList(supplier, map, key1, key2);
  80. return values.add(value);
  81. }
  82. static <K1, K2, V> V addToMap(final Map<K1, Map<K2, V>> map, final K1 key1, final K2 key2,
  83. final V value) {
  84. final Map<K2, V> mapValue = getMap(map, key1);
  85. return mapValue.put(key2, value);
  86. }
  87. static <K1, K2, V> V addToMap(final Supplier<Map<K2, V>> supplier, final Map<K1, Map<K2, V>> map,
  88. final K1 key1, final K2 key2, final V value) {
  89. final Map<K2, V> mapValue = getMap(supplier, map, key1);
  90. return mapValue.put(key2, value);
  91. }
  92. static <K1, V> boolean addToSet(final Map<K1, Set<V>> map, final K1 key1, final V value) {
  93. final Set<V> values = getSet(map, key1);
  94. return values.add(value);
  95. }
  96. static <K1, V> boolean addToTreeSet(final Map<K1, Set<V>> map, final Comparator<V> comparator,
  97. final K1 key1, final V value) {
  98. final Set<V> values = getTreeSet(map, comparator, key1);
  99. return values.add(value);
  100. }
  101. static <K1, V> boolean addToTreeSet(final Map<K1, Set<V>> map, final K1 key1, final V value) {
  102. final Set<V> values = getTreeSet(map, key1);
  103. if (values == null) {
  104. return false;
  105. } else {
  106. return values.add(value);
  107. }
  108. }
  109. static <K, V> MapBuilder<K, V> buildHash() {
  110. final Map<K, V> map = newHash();
  111. return new MapBuilder<>(map);
  112. }
  113. static <K, V> MapBuilder<K, V> buildHashEx() {
  114. final Map<K, V> map = newHash();
  115. return new MapBuilder<>(map);
  116. }
  117. static <K, V> MapBuilder<K, V> buildLinkedHash() {
  118. final Map<K, V> map = newLinkedHash();
  119. return new MapBuilder<>(map);
  120. }
  121. static <K, V> MapBuilder<K, V> buildLinkedHash(final Map<K, V> values) {
  122. final Map<K, V> map = newLinkedHash(values);
  123. return new MapBuilder<>(map);
  124. }
  125. static <K, V> MapBuilder<K, V> buildTree() {
  126. final Map<K, V> map = newTree();
  127. return new MapBuilder<>(map);
  128. }
  129. static <K, V> boolean collectionContains(final Map<K, ? extends Collection<? extends V>> map,
  130. final K key, final V value) {
  131. if (map == null || key == null) {
  132. return false;
  133. } else {
  134. final Collection<? extends V> collection = map.get(key);
  135. if (collection == null) {
  136. return false;
  137. } else {
  138. return collection.contains(value);
  139. }
  140. }
  141. }
  142. static <K1, V> boolean containsInCollection(final Map<K1, ? extends Collection<V>> map,
  143. final K1 key, final V value) {
  144. final Collection<V> collection = map.get(key);
  145. if (collection == null) {
  146. return false;
  147. } else {
  148. return collection.contains(value);
  149. }
  150. }
  151. static <K1, K2, V> boolean containsKey(final Map<K1, Map<K2, V>> map, final K1 key1,
  152. final K2 key2) {
  153. final Map<K2, V> mapValue = getMap(map, key1);
  154. return mapValue.containsKey(key2);
  155. }
  156. static <T> Integer decrementCount(final Map<T, Integer> counts, final T key) {
  157. Integer count = counts.get(key);
  158. if (count == null) {
  159. return 0;
  160. } else {
  161. count--;
  162. if (count <= 0) {
  163. counts.remove(key);
  164. } else {
  165. counts.put(key, count);
  166. }
  167. return count;
  168. }
  169. }
  170. static boolean equalMap1Keys(final Map<String, Object> map1, final Map<String, Object> map2) {
  171. if (map1 == null) {
  172. return false;
  173. } else if (map2 == null) {
  174. return false;
  175. } else {
  176. for (final String key : map1.keySet()) {
  177. final boolean equals = equals(map1, map2, key);
  178. if (!equals) {
  179. return false;
  180. }
  181. }
  182. return true;
  183. }
  184. }
  185. static boolean equals(final Map<String, Object> map1, final Map<String, Object> map2,
  186. final String key) {
  187. final Object value1 = map1.get(key);
  188. final Object value2 = map2.get(key);
  189. final boolean equals = DataType.equal(value1, value2);
  190. return equals;
  191. }
  192. static boolean equalsNotNull(final Map<Object, Object> map1, final Map<Object, Object> map2) {
  193. final Set<Object> keys = new TreeSet<>();
  194. keys.addAll(map1.keySet());
  195. keys.addAll(map2.keySet());
  196. for (final Object key : keys) {
  197. final Object value1 = map1.get(key);
  198. final Object value2 = map2.get(key);
  199. if (!DataType.equal(value1, value2)) {
  200. return false;
  201. }
  202. }
  203. return true;
  204. }
  205. static boolean equalsNotNull(final Map<Object, Object> map1, final Map<Object, Object> map2,
  206. final Collection<? extends CharSequence> exclude) {
  207. final Set<Object> keys = new TreeSet<>();
  208. keys.addAll(map1.keySet());
  209. keys.addAll(map2.keySet());
  210. keys.removeAll(exclude);
  211. for (final Object key : keys) {
  212. final Object value1 = map1.get(key);
  213. final Object value2 = map2.get(key);
  214. if (!DataType.equal(value1, value2, exclude)) {
  215. return false;
  216. }
  217. }
  218. return true;
  219. }
  220. @SuppressWarnings("unchecked")
  221. static boolean equalsNotNull(final Object map1, final Object map2) {
  222. return equalsNotNull((Map<Object, Object>)map1, (Map<Object, Object>)map2);
  223. }
  224. @SuppressWarnings("unchecked")
  225. static boolean equalsNotNull(final Object map1, final Object map2,
  226. final Collection<? extends CharSequence> exclude) {
  227. return equalsNotNull((Map<Object, Object>)map1, (Map<Object, Object>)map2, exclude);
  228. }
  229. @SuppressWarnings({
  230. "unchecked", "rawtypes"
  231. })
  232. static <K, V> Supplier<Map<K, V>> factoryHash() {
  233. return (Supplier)FACTORY_HASH;
  234. }
  235. @SuppressWarnings({
  236. "unchecked", "rawtypes"
  237. })
  238. static <K, V> Supplier<Map<K, V>> factoryLinkedHash() {
  239. return (Supplier)FACTORY_LINKED_HASH;
  240. }
  241. @SuppressWarnings({
  242. "unchecked", "rawtypes"
  243. })
  244. static <K, V> Supplier<Map<K, V>> factoryTree() {
  245. return (Supplier)FACTORY_TREE;
  246. }
  247. static <V> V first(final Map<?, V> map) {
  248. if (Property.hasValue(map)) {
  249. return map.values().iterator().next();
  250. }
  251. return null;
  252. }
  253. @SuppressWarnings("unchecked")
  254. static <K, V> V get(final Map<K, ? extends Object> map, final K key) {
  255. if (map == null) {
  256. return null;
  257. } else {
  258. return (V)map.get(key);
  259. }
  260. }
  261. /**
  262. * Get the value for the key from the map. If the value was null return
  263. * default Value instead. The default value will be added to the map.
  264. *
  265. * @param map The map.
  266. * @param key The key to return the value for.
  267. * @param defaultValue The default value.
  268. * @return The value.
  269. */
  270. static <K, V> V get(final Map<K, ? super V> map, final K key, final V defaultValue) {
  271. if (map == null) {
  272. return defaultValue;
  273. } else {
  274. @SuppressWarnings("unchecked")
  275. final V value = (V)map.get(key);
  276. if (value == null) {
  277. map.put(key, defaultValue);
  278. return defaultValue;
  279. } else {
  280. return value;
  281. }
  282. }
  283. }
  284. static <K, V> V get(final Map<K, V> map, final K key, final Function<K, V> defaultFactory) {
  285. V value = map.get(key);
  286. if (value == null) {
  287. value = defaultFactory.apply(key);
  288. map.put(key, value);
  289. }
  290. return value;
  291. }
  292. static <K, V> V get(final Map<K, V> map, final K key, final Supplier<V> defaultFactory) {
  293. V value = map.get(key);
  294. if (value == null) {
  295. value = defaultFactory.get();
  296. map.put(key, value);
  297. }
  298. return value;
  299. }
  300. @SuppressWarnings({
  301. "unchecked", "rawtypes"
  302. })
  303. static <K, V> V get(final Supplier<V> supplier, final Map<K, ? extends Object> map, final K key) {
  304. V value = (V)map.get(key);
  305. if (value == null) {
  306. value = supplier.get();
  307. ((Map)map).put(key, value);
  308. }
  309. return value;
  310. }
  311. static boolean getBool(final Map<String, ? extends Object> map, final String name) {
  312. final Object value = get(map, name);
  313. if (value == null) {
  314. return false;
  315. } else if (value instanceof Boolean) {
  316. return (Boolean)value;
  317. } else {
  318. return Boolean.parseBoolean(value.toString());
  319. }
  320. }
  321. static boolean getBool(final Map<String, ? extends Object> map, final String name,
  322. final boolean defaultValue) {
  323. final Object value = get(map, name);
  324. if (value == null) {
  325. return defaultValue;
  326. } else if (value instanceof Boolean) {
  327. return (Boolean)value;
  328. } else {
  329. return Boolean.parseBoolean(value.toString());
  330. }
  331. }
  332. static Boolean getBoolean(final Map<String, ? extends Object> map, final String name) {
  333. final Object value = get(map, name);
  334. if (value == null) {
  335. return null;
  336. } else if (value instanceof Boolean) {
  337. return (Boolean)value;
  338. } else {
  339. return Boolean.valueOf(value.toString());
  340. }
  341. }
  342. static <K, C extends Collection<V>, V> C getCollection(final Supplier<C> factory,
  343. final Map<K, C> map, final K key) {
  344. C collection = map.get(key);
  345. if (collection == null && factory != null) {
  346. collection = factory.get();
  347. map.put(key, collection);
  348. }
  349. return collection;
  350. }
  351. static <K1, K2, C extends Collection<V>, V> C getCollection(final Supplier<C> factory,
  352. final Map<K1, Map<K2, C>> map, final K1 key1, final K2 key2) {
  353. final Map<K2, C> map2 = getMap(map, key1);
  354. final C collecion = getCollection(factory, map2, key2);
  355. return collecion;
  356. }
  357. static <T> Integer getCount(final Map<T, Integer> counts, final T key) {
  358. final Integer count = counts.get(key);
  359. if (count == null) {
  360. return 0;
  361. } else {
  362. return count;
  363. }
  364. }
  365. static <K> Double getDouble(final Map<K, ? extends Object> map, final K name) {
  366. final Object value = get(map, name);
  367. if (value == null) {
  368. return null;
  369. } else if (value instanceof Number) {
  370. final Number number = (Number)value;
  371. return number.doubleValue();
  372. } else {
  373. final String stringValue = value.toString();
  374. if (Property.hasValue(stringValue)) {
  375. try {
  376. return Double.valueOf(stringValue);
  377. } catch (final NumberFormatException e) {
  378. return null;
  379. }
  380. } else {
  381. return null;
  382. }
  383. }
  384. }
  385. static <K> double getDouble(final Map<K, ? extends Object> object, final K name,
  386. final double defaultValue) {
  387. final Double value = getDouble(object, name);
  388. if (value == null) {
  389. return defaultValue;
  390. } else {
  391. return value;
  392. }
  393. }
  394. static Double getDoubleValue(final Map<String, ? extends Object> map, final String name) {
  395. final Number value = (Number)get(map, name);
  396. if (value == null) {
  397. return null;
  398. } else {
  399. return value.doubleValue();
  400. }
  401. }
  402. static <K> K getFirstKey(final Map<K, ?> map) {
  403. return map.keySet().iterator().next();
  404. }
  405. static <V> V getFirstValue(final Map<?, V> map) {
  406. return map.values().iterator().next();
  407. }
  408. static <K> Integer getInteger(final Map<K, ? extends Object> map, final K name) {
  409. final Object value = get(map, name);
  410. if (value == null) {
  411. return null;
  412. } else if (value instanceof Number) {
  413. final Number number = (Number)value;
  414. return number.intValue();
  415. } else {
  416. final String stringValue = value.toString();
  417. if (Property.hasValue(stringValue)) {
  418. try {
  419. return Integer.valueOf(stringValue);
  420. } catch (final NumberFormatException e) {
  421. return null;
  422. }
  423. } else {
  424. return null;
  425. }
  426. }
  427. }
  428. static <K> int getInteger(final Map<K, ? extends Object> object, final K name,
  429. final int defaultValue) {
  430. final Integer value = getInteger(object, name);
  431. if (value == null) {
  432. return defaultValue;
  433. } else {
  434. return value;
  435. }
  436. }
  437. static <K, V> List<V> getList(final Map<K, List<V>> map, final K key) {
  438. List<V> list = map.get(key);
  439. if (list == null) {
  440. list = new ArrayList<>();
  441. map.put(key, list);
  442. }
  443. return list;
  444. }
  445. static <K1, K2, V> List<V> getList(final Map<K1, Map<K2, List<V>>> map, final K1 key1,
  446. final K2 key2) {
  447. final Map<K2, List<V>> map2 = getMap(map, key1);
  448. final List<V> list = getList(map2, key2);
  449. return list;
  450. }
  451. static <K1, K2, V> List<V> getList(final Supplier<Map<K2, List<V>>> supplier,
  452. final Map<K1, Map<K2, List<V>>> map, final K1 key1, final K2 key2) {
  453. final Map<K2, List<V>> map2 = getMap(supplier, map, key1);
  454. final List<V> list = getList(map2, key2);
  455. return list;
  456. }
  457. static Long getLong(final Map<String, ? extends Object> map, final String name) {
  458. final Object value = get(map, name);
  459. if (value == null) {
  460. return null;
  461. } else if (value instanceof Number) {
  462. final Number number = (Number)value;
  463. return number.longValue();
  464. } else {
  465. final String stringValue = value.toString();
  466. if (Property.hasValue(stringValue)) {
  467. try {
  468. return Long.valueOf(stringValue);
  469. } catch (final NumberFormatException e) {
  470. return null;
  471. }
  472. } else {
  473. return null;
  474. }
  475. }
  476. }
  477. static long getLong(final Map<String, ? extends Object> map, final String name,
  478. final long defaultValue) {
  479. final Object value = get(map, name);
  480. if (value == null) {
  481. return defaultValue;
  482. } else if (value instanceof Number) {
  483. final Number number = (Number)value;
  484. return number.longValue();
  485. } else {
  486. final String stringValue = value.toString();
  487. if (Property.hasValue(stringValue)) {
  488. try {
  489. return Long.valueOf(stringValue);
  490. } catch (final NumberFormatException e) {
  491. throw new IllegalArgumentException(value + " is not a valid long");
  492. }
  493. } else {
  494. return defaultValue;
  495. }
  496. }
  497. }
  498. static <K1, K2, V> Map<K2, V> getMap(final Map<K1, Map<K2, V>> map, final K1 key) {
  499. Map<K2, V> value = map.get(key);
  500. if (value == null) {
  501. value = newLinkedHash();
  502. map.put(key, value);
  503. }
  504. return value;
  505. }
  506. static <K1, K2, V> V getMap(final Map<K1, Map<K2, V>> map, final K1 key1, final K2 key2) {
  507. final Map<K2, V> values = getMap(map, key1);
  508. return values.get(key2);
  509. }
  510. static <K1, K2, V> V getMap(final Map<K1, Map<K2, V>> map, final K1 key1, final K2 key2,
  511. final Supplier<V> supplier) {
  512. final Map<K2, V> values = getMap(map, key1);
  513. return get(supplier, values, key2);
  514. }
  515. static <K1, K2, V> V getMap(final Map<K1, Map<K2, V>> map, final K1 key1, final K2 key2,
  516. final V defaultValue) {
  517. final Map<K2, V> values = getMap(map, key1);
  518. final V value = values.get(key2);
  519. if (value == null) {
  520. return defaultValue;
  521. } else {
  522. return value;
  523. }
  524. }
  525. static <K1, K2, V> Map<K2, V> getMap(final Supplier<Map<K2, V>> supplier,
  526. final Map<K1, Map<K2, V>> map, final K1 key) {
  527. Map<K2, V> value = map.get(key);
  528. if (value == null) {
  529. value = supplier.get();
  530. map.put(key, value);
  531. }
  532. return value;
  533. }
  534. static <K, V> List<V> getNotNull(final Map<K, V> map, final Collection<K> keys) {
  535. final List<V> values = new ArrayList<>();
  536. if (keys != null) {
  537. for (final K key : keys) {
  538. final V value = map.get(key);
  539. if (value != null) {
  540. values.add(value);
  541. }
  542. }
  543. }
  544. return values;
  545. }
  546. static <K, V> Set<V> getSet(final Map<K, Set<V>> map, final K key) {
  547. Set<V> value = map.get(key);
  548. if (value == null) {
  549. value = new LinkedHashSet<>();
  550. map.put(key, value);
  551. }
  552. return value;
  553. }
  554. static String getString(final Map<String, ? extends Object> map, final String name) {
  555. final Object value = get(map, name);
  556. if (value == null) {
  557. return null;
  558. } else {
  559. return DataTypes.toString(value);
  560. }
  561. }
  562. static String getString(final Map<String, ? extends Object> map, final String name,
  563. final String defaultValue) {
  564. final Object value = get(map, name);
  565. if (value == null) {
  566. return defaultValue;
  567. } else {
  568. return DataTypes.toString(value);
  569. }
  570. }
  571. static <K1, K2, V> Map<K2, V> getTreeMap(final Map<K1, Map<K2, V>> map, final K1 key) {
  572. Map<K2, V> value = map.get(key);
  573. if (value == null) {
  574. value = newTree();
  575. map.put(key, value);
  576. }
  577. return value;
  578. }
  579. static <K, V> Set<V> getTreeSet(final Map<K, Set<V>> map, final Comparator<V> comparator,
  580. final K key) {
  581. Set<V> value = map.get(key);
  582. if (value == null) {
  583. value = new TreeSet<>(comparator);
  584. map.put(key, value);
  585. }
  586. return value;
  587. }
  588. static <K, V> Set<V> getTreeSet(final Map<K, Set<V>> map, final K key) {
  589. if (key == null) {
  590. return null;
  591. } else {
  592. Set<V> value = map.get(key);
  593. if (value == null) {
  594. value = new TreeSet<>();
  595. map.put(key, value);
  596. }
  597. return value;
  598. }
  599. }
  600. static <K1, K2, V> V getValue(final Map<K1, Map<K2, V>> map, final K1 key1, final K2 key2) {
  601. final Map<K2, V> map2 = getMap(map, key1);
  602. return map2.get(key2);
  603. }
  604. static <K> boolean hasValue(final Map<K, ?> map, final K key) {
  605. if (map == null || key == null) {
  606. return false;
  607. } else {
  608. final Object value = map.get(key);
  609. return Property.hasValue(value);
  610. }
  611. }
  612. static boolean isNotNullAndNotZero(final Map<String, Object> object, final String name) {
  613. final Integer value = getInteger(object, name);
  614. if (value == null || value == 0) {
  615. return false;
  616. } else {
  617. return true;
  618. }
  619. }
  620. static <K, V> void mergeCollection(final Map<K, Collection<V>> map,
  621. final Map<K, Collection<V>> otherMap) {
  622. for (final Entry<K, Collection<V>> entry : otherMap.entrySet()) {
  623. final K key = entry.getKey();
  624. Collection<V> collection = map.get(key);
  625. final Collection<V> otherCollection = otherMap.get(key);
  626. if (collection == null) {
  627. collection = BaseCloneable.clone(otherCollection);
  628. map.put(key, collection);
  629. } else {
  630. for (final V value : otherCollection) {
  631. if (!collection.contains(value)) {
  632. collection.add(value);
  633. }
  634. }
  635. }
  636. }
  637. }
  638. static <V, K> HashMap<K, V> newHash() {
  639. return new HashMap<>();
  640. }
  641. static <K, V> Map<K, V> newHash(final K key, final V value) {
  642. final Map<K, V> map = newHash();
  643. map.put(key, value);
  644. return map;
  645. }
  646. static <K, V> Map<K, V> newHash(final Map<K, ? extends V> map) {
  647. final Map<K, V> copy = newHash();
  648. if (map != null) {
  649. copy.putAll(map);
  650. }
  651. return copy;
  652. }
  653. static <K, V> LinkedHashMap<K, V> newLinkedHash() {
  654. return new LinkedHashMap<>();
  655. }
  656. static <K, V> Map<K, V> newLinkedHash(final K key, final V value) {
  657. final Map<K, V> map = newLinkedHash();
  658. map.put(key, value);
  659. return map;
  660. }
  661. static <T1, T2> Map<T1, T2> newLinkedHash(final List<T1> sourceValues,
  662. final List<T2> targetValues) {
  663. final Map<T1, T2> map = newLinkedHash();
  664. for (int i = 0; i < sourceValues.size() && i < targetValues.size(); i++) {
  665. final T1 sourceValue = sourceValues.get(i);
  666. final T2 targetValue = targetValues.get(i);
  667. map.put(sourceValue, targetValue);
  668. }
  669. return map;
  670. }
  671. static <K, V> Map<K, V> newLinkedHash(final Map<K, ? extends V> map) {
  672. final Map<K, V> copy = newLinkedHash();
  673. if (map != null) {
  674. copy.putAll(map);
  675. }
  676. return copy;
  677. }
  678. static MapEx newLinkedHashEx(final Map<String, ? extends Object> map) {
  679. final MapEx copy = JsonObject.hash();
  680. if (map != null) {
  681. copy.putAll(map);
  682. }
  683. return copy;
  684. }
  685. static <K, V> Map<K, V> newTree() {
  686. return new TreeMap<>();
  687. }
  688. static <K extends Comparable<K>, V extends Comparable<V>> TreeMap<K, V> newTree(
  689. final Comparator<K> comparator) {
  690. return new TreeMap<>(comparator);
  691. }
  692. static <K, V> Map<K, V> newTree(final Comparator<K> comparator, final Map<K, ? extends V> map) {
  693. final Map<K, V> newMap = newTree();
  694. if (map != null) {
  695. newMap.putAll(map);
  696. }
  697. return newMap;
  698. }
  699. static <K, V> Map<K, V> newTree(final K key, final V value) {
  700. final Map<K, V> map = newTree();
  701. map.put(key, value);
  702. return map;
  703. }
  704. static <K, V> Map<K, V> newTree(final Map<K, ? extends V> map) {
  705. final Map<K, V> newMap = newTree();
  706. if (map != null) {
  707. newMap.putAll(map);
  708. }
  709. return newMap;
  710. }
  711. static <K1, K2, V> V put(final Map<K1, Map<K2, V>> map, final K1 key1, final K2 key2,
  712. final V value) {
  713. final Map<K2, V> values = getMap(map, key1);
  714. return values.put(key2, value);
  715. }
  716. static <K1, K2, V> V put(final Supplier<Map<K2, V>> factory, final Map<K1, Map<K2, V>> map,
  717. final K1 key1, final K2 key2, final V value) {
  718. final Map<K2, V> values = getMap(factory, map, key1);
  719. return values.put(key2, value);
  720. }
  721. static void putAll(final Map<String, Object> map,
  722. final Map<String, ? extends Object> properties) {
  723. if (map != null && properties != null) {
  724. for (final Entry<String, ? extends Object> entry : properties.entrySet()) {
  725. final String key = entry.getKey();
  726. final Object value = entry.getValue();
  727. map.put(key, value);
  728. }
  729. }
  730. }
  731. static void putAll(final Map<String, Object> map, final Properties properties) {
  732. if (map != null && properties != null) {
  733. for (final Entry<Object, Object> entry : properties.entrySet()) {
  734. final String key = (String)entry.getKey();
  735. final Object value = entry.getValue();
  736. map.put(key, value);
  737. }
  738. }
  739. }
  740. static <K, V extends Comparable<V>> void putIfGreaterThan(final Map<K, V> map, final K key,
  741. final V value) {
  742. synchronized (map) {
  743. final V lastValue = map.get(key);
  744. if (lastValue == null || value.compareTo(lastValue) > 1) {
  745. map.put(key, value);
  746. }
  747. }
  748. }
  749. static <K, V> boolean removeFromCollection(final Map<K, ? extends Collection<V>> map, final K key,
  750. final V value) {
  751. final Collection<V> values = map.get(key);
  752. if (values == null) {
  753. return false;
  754. } else {
  755. final boolean removed = values.remove(value);
  756. if (values.isEmpty()) {
  757. map.remove(key);
  758. }
  759. return removed;
  760. }
  761. }
  762. static <K1, K2, V> V removeFromMap(final Map<K1, Map<K2, V>> map, final K1 key1, final K2 key2) {
  763. final Map<K2, V> values = map.get(key1);
  764. if (values == null) {
  765. return null;
  766. } else {
  767. final V value = values.remove(key2);
  768. if (values.isEmpty()) {
  769. map.remove(key1);
  770. }
  771. return value;
  772. }
  773. }
  774. static <K, V> boolean removeFromSet(final Map<K, Set<V>> map, final K key, final V value) {
  775. final Set<V> values = map.get(key);
  776. if (values == null) {
  777. return false;
  778. } else {
  779. final boolean removed = values.remove(value);
  780. if (values.isEmpty()) {
  781. map.remove(key);
  782. }
  783. return removed;
  784. }
  785. }
  786. static <K, V extends Comparable<V>> void removeIfGreaterThanEqual(final Map<K, V> map,
  787. final K key, final V value) {
  788. synchronized (map) {
  789. final V lastValue = map.get(key);
  790. if (lastValue == null || value.compareTo(lastValue) >= 0) {
  791. map.remove(key);
  792. }
  793. }
  794. }
  795. static <K, V extends Comparable<V>> void removeIfLessThanEqual(final Map<K, V> map, final K key,
  796. final V value) {
  797. synchronized (map) {
  798. final V lastValue = map.get(key);
  799. if (lastValue == null || value.compareTo(lastValue) <= 0) {
  800. map.remove(key);
  801. }
  802. }
  803. }
  804. /**
  805. * Retain the value for the key in the map if the map's value is not equal to the value.
  806. * This can be used to create a set of keys values that need to be updated.
  807. *
  808. * @param map
  809. * @param key
  810. * @param value
  811. * @return True if the value was retained (not equal).
  812. */
  813. static <K, V> boolean retainIfNotEqual(final Map<K, V> map, final K key, final V value) {
  814. final Object currentValue = map.get(key);
  815. if (DataType.equal(currentValue, value)) {
  816. map.remove(key);
  817. return false;
  818. } else {
  819. return true;
  820. }
  821. }
  822. /**
  823. * Retain the value for the key in the map if the map's value is not equal to the value.
  824. * This can be used to create a set of keys values that need to be updated.
  825. *
  826. * @param map
  827. * @param key
  828. * @param value
  829. * @return True if the value was retained (not equal).
  830. */
  831. static <K, V> void retainIfNotEqual(final Map<K, V> map1, final Map<K, V> map2) {
  832. for (final Entry<K, V> entry : map2.entrySet()) {
  833. final K key = entry.getKey();
  834. final V value = entry.getValue();
  835. retainIfNotEqual(map1, key, value);
  836. }
  837. }
  838. static <K extends Comparable<K>, V extends Comparable<V>> Map<K, V> sortByValues(
  839. final Map<K, V> map) {
  840. final MapValueComparator<K, V> comparator = new MapValueComparator<>(map);
  841. final Map<K, V> sortedMap = newTree(comparator);
  842. sortedMap.putAll(map);
  843. return newLinkedHash(sortedMap);
  844. }
  845. static Map<String, Object> toMap(final Preferences preferences) {
  846. try {
  847. final Map<String, Object> map = newHash();
  848. for (final String name : preferences.keys()) {
  849. final Object value = preferences.get(name, null);
  850. map.put(name, value);
  851. }
  852. return map;
  853. } catch (final BackingStoreException e) {
  854. throw new RuntimeException("Unable to get preferences " + e);
  855. }
  856. }
  857. static Map<String, String> toMap(final String string) {
  858. if (string == null) {
  859. return Collections.emptyMap();
  860. } else {
  861. final Map<String, String> map = newLinkedHash();
  862. for (final String entry : string.split("\n")) {
  863. final String[] pair = entry.split("=");
  864. if (pair.length == 2) {
  865. final String name = pair[0];
  866. final String value = pair[1];
  867. map.put(name, value);
  868. } else {
  869. System.err.println("Invalid entry: " + entry);
  870. }
  871. }
  872. return map;
  873. }
  874. }
  875. }