java:java.util.Map和java.util.Set的Key类型转换
来源:互联网 发布:淘宝外观专利权投诉 编辑:程序博客网 时间:2024/06/08 17:46
google的guava项目提对Map供了丰富强大的转换功能(参见guava jar包中的com.google.common.collect.Maps )
Maps.transform系列方法可以对Map的Value类型进行转换,
比如: public static <K, V1, V2> Map<K, V2> transformEntries( Map<K, V1> fromMap,EntryTransformer<? super K, ? super V1, V2> transformer)
可以将一个Map<K,V1>
转为一个Map<K,V2>
对象。
但是guava中并没有提供对Key的类型转换。为什么呢?
对Map提供Key类型转换不一定是安全的,是有风险的。比如用ByteBuffer->byte[],我们知道 byte[]
做Key是有问题的(因为两个内容相同的byte[]
计算出的hashcode不同,所以在一般的设计中不会用byte[]
做为key)。
虽然实现Key类型转换并不复杂,但guava中并没有将它做为通用方法提供,以防止错误使用。对于java.util.Set也没有提供transform方法,道理是一样的。
但是在现实设计中有的时候真的需要一个Key类型的转换,就需要自己来实现它,于是我参照guava中transform的设计,自己实现了java.util.Map
和java.util.Set
的Key类型转换方法(不依赖guava)。
如下图,
其实核心的方法就是两个静态方法,如上图红框标的,一个用于转换Map<K1,V>
到Map<K2,V>
,另一个用来转换Set<E1>
到Set<E2>
TransformedMap<K1, K2, V>
,TransformedSet<E1, E2>
两个内部类就是对应上面两个方法的实现部分.
Set和Map的转换核心是Iterator的转换,所以从guava中抄了TransformedIterator<F, T>
的代码实现。
完整实现代码如下:
CollectionUtils.java
package net.gdface.facelog.client;import java.util.AbstractMap;import java.util.AbstractSet;import java.util.Iterator;import java.util.Map;import java.util.Set;public class CollectionUtils { private CollectionUtils() {} public static interface Function<F, T> { T apply( F input); } /** * dual transform type between L and R<br> * {@link #toRight(Object)} L -> R<br> * {@link #fromRight(Object)} R -> L * @author guyadong * * @param <L> left type * @param <R> right type */ public static interface DualTransformer<L,R>{ R toRight(L input); L fromRight(R input); } public static final <L,R> DualTransformer<L,R> asDualTransformer(final Function<L,R> t1,final Function<R,L>t2){ checkNotNull(t1); checkNotNull(t2); return new DualTransformer<L,R>(){ @Override public R toRight(L input) { return t1.apply(input); } @Override public L fromRight(R input) { return t2.apply(input); } }; } public static final <L,R> Function<L,R> asToRightTransformer(final DualTransformer<L,R> dual){ checkNotNull(dual); return new Function<L,R>(){ @Override public R apply(L input) { return dual.toRight(input); } }; } public static final <L,R> Function<R,L> asFromRightTransformer(final DualTransformer<L,R> dual){ checkNotNull(dual); return new Function<R,L>(){ @Override public L apply(R input) { return dual.fromRight(input); } }; } private static boolean equal( Object a, Object b) { return a == b || (a != null && a.equals(b)); } static <T> T checkNotNull(T reference) { if (reference == null) { throw new NullPointerException(); } return reference; } static <V> V safeGet(Map<?, V> map, Object key) { checkNotNull(map); try { return map.get(key); } catch (ClassCastException e) { return null; } catch (NullPointerException e) { return null; } } /** @see #tranformKeys(Map, DualTransformer)*/ public static final<K1,K2,V>Map<K2,V> tranformKeys(Map<K1,V>fromMap, Function<K1, K2> transformer2, Function<K2, K1> transformer1){ return tranformKeys(fromMap,asDualTransformer(transformer2,transformer1)); } /** * Returns a view of a map where each value is transformed by a function. All * other properties of the map, such as iteration order, are left intact. <br> * see also {@link com.google.common.collect.Maps#transformEntries(Map, com.google.common.collect.Maps.EntryTransformer)} * @param fromMap * @param transformer * @return */ public static final<K1,K2,V>Map<K2,V> tranformKeys(Map<K1,V>fromMap, DualTransformer<K1, K2> transformer){ return new TransformedMap<K1, K2, V>(fromMap,transformer); } /** @see #transform(Set, DualTransformer)*/ public static final <E1,E2>Set<E2>transform(Set<E1> fromSet, Function<E1, E2> transformer2, Function<E2, E1> transformer1){ return transform(fromSet,asDualTransformer(transformer2,transformer1)); } /** * Returns a view of a set where each key is transformed by a function. All * other properties of the map, such as iteration order, are left intact. <br> * see also {@link com.google.common.collect.Maps#transformEntries(Map, com.google.common.collect.Maps.EntryTransformer)} * @param fromSet * @param transformer * @return */ public static final <E1,E2>Set<E2>transform(Set<E1> fromSet, DualTransformer<E1,E2> transformer){ return new TransformedSet<E1,E2>(fromSet,transformer); } /** * Returns an iterator that applies {@code function} to each element of {@code fromIterator}.<br> * see also {@link com.google.common.collect.Iterators#transform(Iterator, com.google.common.base.Function)} * @param fromIterator * @param transformer * @return */ public static <F, T> Iterator<T> transform(final Iterator<F> fromIterator, final Function<? super F, ? extends T> transformer) { return new TransformedIterator<F, T>(fromIterator,transformer); } static class TransformedIterator<F, T> implements Iterator<T> { final Iterator<? extends F> backingIterator; private Function<? super F, ? extends T> transformer; TransformedIterator(Iterator<? extends F> backingIterator,Function<? super F, ? extends T> transformer) { this.backingIterator = checkNotNull(backingIterator); this.transformer = checkNotNull(transformer); } @Override public final boolean hasNext() { return backingIterator.hasNext(); } @Override public final T next() { return transformer.apply(backingIterator.next()); } @Override public final void remove() { backingIterator.remove(); } } static class TransformedSet<E1, E2> extends AbstractSet<E2> { final Set<E1> fromSet; private final DualTransformer<E1, E2> transformer; TransformedSet(Set<E1> fromSet, DualTransformer<E1, E2> transformer) { checkNotNull(fromSet); checkNotNull(transformer); this.fromSet = fromSet; this.transformer = transformer; } @Override public int size() { return fromSet.size(); } @Override public Iterator<E2> iterator() { return transform(fromSet.iterator(), asToRightTransformer(transformer)); } @Override public boolean add(E2 e) { return fromSet.add(transformer.fromRight(e)); } @SuppressWarnings("unchecked") @Override public boolean contains(Object o) { try { return fromSet.contains(transformer.fromRight((E2) o)); } catch (ClassCastException e) { return false; } } @SuppressWarnings("unchecked") @Override public boolean remove(Object o) { try { return fromSet.remove(transformer.fromRight((E2) o)); } catch (ClassCastException e) { return false; } } } static class TransformedMap<K1, K2, V> extends AbstractMap<K2, V> { final Map<K1, V> fromMap; private DualTransformer<K1,K2> transformer; TransformedMap(Map<K1, V> fromMap, DualTransformer<K1,K2> transformer) { checkNotNull(fromMap); checkNotNull(transformer); this.fromMap = fromMap; this.transformer = transformer; } @SuppressWarnings("unchecked") @Override public V get(Object key) { try { return fromMap.get(transformer.fromRight((K2) key)); } catch (ClassCastException e) { return null; } } @SuppressWarnings("unchecked") @Override public boolean containsKey(Object key) { try { return fromMap.containsKey(transformer.fromRight((K2) key)); } catch (ClassCastException e) { return false; } } @Override public V put(K2 key, V value) { return fromMap.put(transformer.fromRight(key), value); } @SuppressWarnings("unchecked") @Override public V remove(Object key) { try { return fromMap.remove(transformer.fromRight((K2) key)); } catch (ClassCastException e) { return null; } } @Override public Set<Entry<K2, V>> entrySet() { return new EntrySet<K2,V>(){ @Override Map<K2, V> map() { return TransformedMap.this; } @Override public Iterator<java.util.Map.Entry<K2, V>> iterator() { return transform(fromMap.entrySet().iterator(), new Function<Entry<K1,V>,Entry<K2,V>>(){ @Override public java.util.Map.Entry<K2, V> apply(java.util.Map.Entry<K1, V> input) { return new TransformedEntry<K1,K2,V>(input,asToRightTransformer(TransformedMap.this.transformer)); }}); }}; } abstract static class EntrySet<K, V> extends AbstractSet<Entry<K, V>> { abstract Map<K, V> map(); @Override public int size() { return map().size(); } @Override public boolean contains(Object o) { if (o instanceof Entry) { Entry<?, ?> entry = (Entry<?, ?>) o; Object key = entry.getKey(); V value = safeGet(map(), key); return equal(value, entry.getValue()) && (value != null || map().containsKey(entry.getKey())); } return false; } @Override public boolean remove(Object o) { if (contains(o)) { Entry<?, ?> entry = (Entry<?, ?>) o; return map().keySet().remove(entry.getKey()); } return false; } } static class TransformedEntry<K1,K2,V> implements Entry<K2, V> { final Entry<K1,V>fromEntry; final Function<K1, K2> transformer2; TransformedEntry(Entry<K1,V>fromEntry,Function<K1, K2> transformer2){ checkNotNull(fromEntry); this.fromEntry = fromEntry; checkNotNull(transformer2); this.transformer2 = transformer2; } @Override public K2 getKey() { return transformer2.apply(fromEntry.getKey()); } @Override public V getValue() { return fromEntry.getValue(); } @Override public V setValue(V value) { return fromEntry.setValue(value); } @Override public boolean equals(Object object) { if(object instanceof TransformedEntry){ return fromEntry.equals((TransformedEntry<?, ?, ?>)object); } return super.equals(object); } @Override public int hashCode() { return fromEntry.hashCode(); } @Override public String toString() { return fromEntry.toString(); } } }}
注意:
transfrom方法返回的新对象是原对象的代理对象,对新对象的任何操作实际都是原对象的操作
- java:java.util.Map和java.util.Set的Key类型转换
- guava:java:java.util.Map和java.util.Set的Key类型转换
- 维护java.util.Set, java.util.Map的插入顺序
- java.util.Date的set方法问题(struts2类型转换)
- import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeMap; /*
- java.util.Map的衍生
- java.util.Set翻译
- java.util.Set翻译
- java.util.Set
- java.util.Set 排序
- java.util.Set<E>
- java.util.Map翻译
- java.util 中 map
- java.util.Map接口
- java.util.Map
- java.util.Map
- java.util.Map
- java.util.Date的转换
- project CoberturaMaven: com.ctc.wstx.exc.WstxIOException:Invalid UTF-8 start byte 0xac (at char #1
- Jmeter学习—005—JMeter命令行(非GUI模式)执行详解
- php的PDO
- Linux 软/硬链接
- NOIP 2003 加分二叉树
- java:java.util.Map和java.util.Set的Key类型转换
- Centos之ifconfig 命令找不到(ifconfig command not found) -yellowcong
- 文章标题
- Caused by: org.xml.sax.SAXParseException; 通配符的匹配很全面, 但无法找到元素 'context:property-placeholder' 的声明。
- 学习心得
- 低车速下,扭矩如何增加
- jQuery选择器
- 写给我的JAVA工程师之路-数据表操作
- Agisoft PhotoScan Pro 1.4.0.5076 Win64 1CD