/* * This is free and unencumbered software released into the public domain. * * Anyone is free to copy, modify, publish, use, compile, sell, or * distribute this software, either in source code form or as a compiled * binary, for any purpose, commercial or non-commercial, and by any * means. * * In jurisdictions that recognize copyright laws, the author or authors * of this software dedicate any and all copyright interest in the * software to the public domain. We make this dedication for the benefit * of the public at large and to the detriment of our heirs and * successors. We intend this dedication to be an overt act of * relinquishment in perpetuity of all present and future rights to this * software under copyright law. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * For more information, please refer to <http://unlicense.org/> */ package java.util; import java.util.function.BiConsumerEx; import java.util.function.BiFunction; import java.util.function.BiFunctionEx; import java.util.function.Function; import java.util.function.FunctionEx; import jxtn.core.axi.collections.MappedMap; /** * {@link Map}的延伸功能。 * * @author AqD * @param <K> 鍵值型態 * @param <V> 項目值型態 */ public interface MapExt<K, V> { ////////////////////////////////////////////////////////////////////////// // 泛型方法 // /** * 針對每個鍵值及項目值執行指定動作 * * @param <TException> 動作可拋出的例外型態 * @param action 要執行的動作 * @throws TException 表示{@code action}丟出例外 */ default <TException extends Exception> void forEachEx( BiConsumerEx<? super K, ? super V, ? extends TException> action) throws TException { Objects.requireNonNull(action); Map<K, V> thiz = (Map<K, V>) this; for (Map.Entry<K, V> entry : thiz.entrySet()) { K k; V v; try { k = entry.getKey(); v = entry.getValue(); } catch (IllegalStateException ise) { throw new ConcurrentModificationException(ise); } action.acceptEx(k, v); } } ////////////////////////////////////////////////////////////////////////// // 項目轉換 // /** * 依照對照函數建立對照{@link Map}。 * * @param <V2> 對照項目值型態 * @param mapper 對照項目值的函數 * @return 對照項目值的唯讀{@link Map},依賴原有的{@link Map} */ default <V2> Map<K, V2> mapValues(Function<? super V, ? extends V2> mapper) { Map<K, V> thiz = (Map<K, V>) this; return new MappedMap<>(thiz, (k, v) -> mapper.apply(v)); } /** * 依照對照函數建立對照{@link Map}。 * * @param <V2> 對照項目值型態 * @param mapper 對照項目值的函數 * @return 對照項目值的唯讀{@link Map},依賴原有的{@link Map} */ default <V2> Map<K, V2> mapValues(BiFunction<? super K, ? super V, ? extends V2> mapper) { Map<K, V> thiz = (Map<K, V>) this; return new MappedMap<>(thiz, mapper); } ////////////////////////////////////////////////////////////////////////// // 項目統整 // /** * 對照目前的項目值以產生新的{@link HashMap}。 * * @param <V2> 對照項目值型態 * @param <VException> 計算項目值函數可拋出的例外型態 * @param mapper 對照項目值的函數 * @return 對照後的新{@link HashMap}(不依賴原有的) * @throws VException 表示{@code mapper}丟出例外 */ default <V2, VException extends Exception> HashMap<K, V2> toHashMapMapped( FunctionEx<? super V, ? extends V2, ? extends VException> mapper) throws VException { Map<K, V> thiz = (Map<K, V>) this; HashMap<K, V2> result = new HashMap<>(thiz.size()); for (Map.Entry<K, V> entry : thiz.entrySet()) { V2 newValue = mapper.applyEx(entry.getValue()); result.put(entry.getKey(), newValue); } return result; } /** * 對照目前的項目值以產生新的{@link HashMap}。 * * @param <K2> 對照鍵值型態 * @param <V2> 對照項目值型態 * @param <KException> 計算鍵值函數可拋出的例外型態 * @param <VException> 計算項目值函數可拋出的例外型態 * @param keyMapper 對照鍵值的函數 * @param valueMapper 對照項目值的函數 * @return 對照後的新{@link HashMap}(不依賴原有的) * @throws KException 表示{@code keyMapper}丟出例外 * @throws VException 表示{@code valueMapper}丟出例外 */ default <K2, V2, KException extends Exception, VException extends Exception> HashMap<K2, V2> toHashMapMapped( FunctionEx<? super K, ? extends K2, ? extends KException> keyMapper, FunctionEx<? super V, ? extends V2, ? extends VException> valueMapper) throws KException, VException { Map<K, V> thiz = (Map<K, V>) this; HashMap<K2, V2> result = new HashMap<>(thiz.size()); for (Map.Entry<K, V> entry : thiz.entrySet()) { K2 newKey = keyMapper.applyEx(entry.getKey()); V2 newVal = valueMapper.applyEx(entry.getValue()); result.put(newKey, newVal); } return result; } /** * 對照目前的項目值以產生新的{@link HashMap}。 * * @param <V2> 對照項目值型態 * @param <VException> 計算項目值函數可拋出的例外型態 * @param mapper 對照項目值的函數 * @return 對照後的新{@link HashMap}(不依賴原有的) * @throws VException 表示{@code mapper}丟出例外 */ default <V2, VException extends Exception> HashMap<K, V2> toHashMapMapped( BiFunctionEx<? super K, ? super V, V2, ? extends VException> mapper) throws VException { Map<K, V> thiz = (Map<K, V>) this; HashMap<K, V2> result = new HashMap<>(thiz.size()); for (Map.Entry<K, V> entry : thiz.entrySet()) { K oldKey = entry.getKey(); V2 newValue = mapper.applyEx(oldKey, entry.getValue()); result.put(oldKey, newValue); } return result; } /** * 對照目前的項目值以產生新的{@link HashMap}。 * * @param <K2> 對照鍵值型態 * @param <V2> 對照項目值型態 * @param <KException> 計算鍵值函數可拋出的例外型態 * @param <VException> 計算項目值函數可拋出的例外型態 * @param keyMapper 對照鍵值的函數 * @param valueMapper 對照項目值的函數 * @return 對照後的新{@link HashMap}(不依賴原有的) * @throws KException 表示{@code keyMapper}丟出例外 * @throws VException 表示{@code valueMapper}丟出例外 */ default <K2, V2, KException extends Exception, VException extends Exception> HashMap<K2, V2> toHashMapMapped( BiFunctionEx<? super K, ? super V, K2, ? extends KException> keyMapper, BiFunctionEx<? super K, ? super V, V2, ? extends VException> valueMapper) throws KException, VException { Map<K, V> thiz = (Map<K, V>) this; HashMap<K2, V2> result = new HashMap<>(thiz.size()); for (Map.Entry<K, V> entry : thiz.entrySet()) { K oldKey = entry.getKey(); V oldVal = entry.getValue(); K2 newKey = keyMapper.applyEx(oldKey, oldVal); V2 newVal = valueMapper.applyEx(oldKey, oldVal); result.put(newKey, newVal); } return result; } /** * 對照目前的項目值以產生新的{@link TreeMap}。 * * @param <V2> 對照項目值型態 * @param <VException> 計算項目值函數可拋出的例外型態 * @param mapper 對照項目值的函數 * @return 對照後的新{@link TreeMap}(不依賴原有的) * @throws VException 表示{@code mapper}丟出例外 */ default <V2, VException extends Exception> TreeMap<K, V2> toTreeMapMapped( FunctionEx<? super V, ? extends V2, ? extends VException> mapper) throws VException { Map<K, V> thiz = (Map<K, V>) this; TreeMap<K, V2> result = new TreeMap<>(); for (Map.Entry<K, V> entry : thiz.entrySet()) { V2 newValue = mapper.applyEx(entry.getValue()); result.put(entry.getKey(), newValue); } return result; } /** * 對照目前的項目值以產生新的{@link TreeMap}。 * * @param <K2> 對照鍵值型態 * @param <V2> 對照項目值型態 * @param <KException> 計算鍵值函數可拋出的例外型態 * @param <VException> 計算項目值函數可拋出的例外型態 * @param keyMapper 對照鍵值的函數 * @param valueMapper 對照項目值的函數 * @return 對照後的新{@link TreeMap}(不依賴原有的) * @throws KException 表示{@code keyMapper}丟出例外 * @throws VException 表示{@code valueMapper}丟出例外 */ default <K2, V2, KException extends Exception, VException extends Exception> TreeMap<K2, V2> toTreeMapMapped( FunctionEx<? super K, ? extends K2, ? extends KException> keyMapper, FunctionEx<? super V, ? extends V2, ? extends VException> valueMapper) throws KException, VException { Map<K, V> thiz = (Map<K, V>) this; TreeMap<K2, V2> result = new TreeMap<>(); for (Map.Entry<K, V> entry : thiz.entrySet()) { K2 newKey = keyMapper.applyEx(entry.getKey()); V2 newVal = valueMapper.applyEx(entry.getValue()); result.put(newKey, newVal); } return result; } /** * 對照目前的項目值以產生新的{@link TreeMap}。 * * @param <V2> 對照項目值型態 * @param <VException> 計算項目值函數可拋出的例外型態 * @param mapper 對照項目值的函數 * @return 對照後的新{@link TreeMap}(不依賴原有的) * @throws VException 表示{@code mapper}丟出例外 */ default <V2, VException extends Exception> TreeMap<K, V2> toTreeMapMapped( BiFunctionEx<? super K, ? super V, V2, ? extends VException> mapper) throws VException { Map<K, V> thiz = (Map<K, V>) this; TreeMap<K, V2> result = new TreeMap<>(); for (Map.Entry<K, V> entry : thiz.entrySet()) { K oldKey = entry.getKey(); V2 newValue = mapper.applyEx(oldKey, entry.getValue()); result.put(oldKey, newValue); } return result; } /** * 對照目前的項目值以產生新的{@link TreeMap}。 * * @param <K2> 對照鍵值型態 * @param <V2> 對照項目值型態 * @param <KException> 計算鍵值函數可拋出的例外型態 * @param <VException> 計算項目值函數可拋出的例外型態 * @param keyMapper 對照鍵值的函數 * @param valueMapper 對照項目值的函數 * @return 對照後的新{@link TreeMap}(不依賴原有的) * @throws KException 表示{@code keyMapper}丟出例外 * @throws VException 表示{@code valueMapper}丟出例外 */ default <K2, V2, KException extends Exception, VException extends Exception> TreeMap<K2, V2> toTreeMapMapped( BiFunctionEx<? super K, ? super V, K2, ? extends KException> keyMapper, BiFunctionEx<? super K, ? super V, V2, ? extends VException> valueMapper) throws KException, VException { Map<K, V> thiz = (Map<K, V>) this; TreeMap<K2, V2> result = new TreeMap<>(); for (Map.Entry<K, V> entry : thiz.entrySet()) { K oldKey = entry.getKey(); V oldVal = entry.getValue(); K2 newKey = keyMapper.applyEx(oldKey, oldVal); V2 newVal = valueMapper.applyEx(oldKey, oldVal); result.put(newKey, newVal); } return result; } }