除了迭代HashMultiset<String>
中的所有条目外,还有一些技巧可以将Map<String,Integer>
转换为Set
吗?
更新:整数应表示多集中字符串的计数。
答案 0 :(得分:13)
您可以使用Maps.asMap。使用lambda表达式(Java 8),它将是一个单行程序:
Maps.asMap(multiset.elementSet(), elem -> multiset.count(elem));
在Java 7及以下版本中:
final Multiset<String> multiset = HashMultiset.create();
Map<String, Integer> freqMap = Maps.asMap(multiset.elementSet(),
new Function<String, Integer>() {
@Override
public Integer apply(String elem) {
return multiset.count(elem);
}
});
答案 1 :(得分:3)
使用Eclipse Collections,您可以在Bag
(也称为Multiset)上使用toMapOfItemToCount
方法,该方法将在Map
中返回Bag
的相同类型的密钥{1}}和Integer
次。
注意:我是Eclipse集合的提交者。
答案 2 :(得分:1)
您可以简单地遍历条目并将元素和计数放到地图上。
public class MultisetToMap {
public static <E> Map<E, Integer> convert(Multiset<E> multiset) {
Map<E, Integer> map = Maps.newHashMap();
for (E e : multiset) {
multiset.count(e);
map.put(e, multiset.count(e));
}
return map;
}
}
下面是(通过)JUnit测试。
@Test
public void testConvert() {
HashMultiset<String> hashMultiset = HashMultiset.create();
hashMultiset.add("a");
hashMultiset.add("a");
hashMultiset.add("a");
hashMultiset.add("b");
hashMultiset.add("c");
Map<String, Integer> map = MultisetToMap.convert(hashMultiset);
assertEquals((Integer) 3, map.get("a"));
assertEquals((Integer) 1, map.get("b"));
assertEquals((Integer) 1, map.get("c"));
}
答案 3 :(得分:1)
如果你真的想避免循环遍历Multiset
的条目,你可以创建一个视图作为地图:
public class MultisetMapView<E> implements Map<E, Integer> {
private Multiset<E> delegate;
public MultisetMapView(Multiset<E> delegate) {
this.delegate = delegate;
}
public int size() {
return delegate.size();
}
public boolean isEmpty() {
return delegate.isEmpty();
}
public boolean containsKey(Object key) {
return delegate.contains(key);
}
public boolean containsValue(Object value) {
throw new UnsupportedOperationException();
}
public Integer get(Object key) {
return delegate.count(key);
}
public Integer put(E key, Integer value) {
return delegate.setCount(key, value);
}
public Integer remove(Object key) {
int count = delegate.count(key);
delegate.remove(key);
return count;
}
public void putAll(Map<? extends E, ? extends Integer> m) {
for (Entry<? extends E, ? extends Integer> entry : m.entrySet()) {
delegate.setCount(entry.getKey(), entry.getValue());
}
}
public void clear() {
delegate.clear();
}
public Set<E> keySet() {
return delegate.elementSet();
}
public Collection<Integer> values() {
throw new UnsupportedOperationException();
}
public Set<java.util.Map.Entry<E, Integer>> entrySet() {
Set<java.util.Map.Entry<E, Integer>> entrySet = Sets.newHashSet();
for (E e : delegate) {
delegate.count(e);
entrySet.add(Maps.immutableEntry(e, delegate.count(e)));
}
return entrySet;
}
}
在我的实施中,我拒绝实施containsValue
和values
方法,因为这些方法在上下文中没用。如果需要,可以通过循环访问条目并检查遇到的元素的count
来实现这些。
再次,你可以看到这个在这个JUnit案例中工作:
@Test
public void testConvert() {
HashMultiset<String> hashMultiset = HashMultiset.create();
hashMultiset.add("a");
hashMultiset.add("a");
hashMultiset.add("a");
hashMultiset.add("b");
hashMultiset.add("c");
Map<String, Integer> map = new MultisetMapView<String>(hashMultiset);
assertEquals((Integer) 3, map.get("a"));
assertEquals((Integer) 1, map.get("b"));
assertEquals((Integer) 1, map.get("c"));
}
答案 4 :(得分:0)
这是可能的,但只有反射才能看起来非常不安全。
HashMultiset<String> hashMultiset = HashMultiset.create();
hashMultiset.add("a");
hashMultiset.add("a");
hashMultiset.add("a");
hashMultiset.add("b");
hashMultiset.add("c");
System.out.println(hashMultiset);
Method method = hashMultiset.getClass().getSuperclass().getDeclaredMethod("backingMap");
method.setAccessible(true);
Map<String, Integer> map = (Map<String, Integer>) method.invoke(hashMultiset);
System.out.println(map);
结果:
[b, c, a x 3]
{b=1, c=1, a=3}