How to convert HashMultiset <String> to Map <String, Integer>

Is there any trick to converting HashMultiset<String> to Map<String,Integer> , except for repeating all the entries in Set ?
Update: Integer should represent the number of rows in the multiset.

+7
java collections guava
source share
6 answers

Updated to java 8, here is what I found as the best answer (based on other answers):

 public static <E> Map<E, Integer> convert(Multiset<E> multiset) { return multiset.entrySet().stream().collect( Collectors.toMap(x->x.getElement(),x->x.getCount())); } 

or

 public static <E> Map<E, Integer> convert(Multiset<E> multiset) { return multiset.entrySet().stream().collect( Collectors.toMap(Entry::getElement,Entry::getCount)); } 
+4
source share

You can use Maps.asMap . With a lambda expression (Java 8), it will be single-line:

 Maps.asMap(multiset.elementSet(), elem -> multiset.count(elem)); 

In Java 7 and below:

 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); } }); 
+10
source share

With Eclipse Collections, you can use the toMapOfItemToCount method on a Bag (aka Multiset), which will return a Map with a key of the same type in the Bag and Integer counter.

Note. I am a committer for Eclipse collections.

+3
source share

You can simply scroll through the entries and place the item and count the map.

 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; } } 

Below is a test (passing) of 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")); } 
+1
source share

If you really want to avoid Multiset over entries from Multiset , you can create an idea of ​​it as a map:

 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; } } 

In my implementation, I refused to implement the containsValue and values methods because they are not useful in context. If desired, they can be implemented by scrolling through the records and checking the count elements found.

And again you can see how this works in this case of 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")); } 
+1
source share

It is possible, but only with reflection, and it looks very dangerous.

  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); 

Result:

 [b, c, ax 3] {b=1, c=1, a=3} 
0
source share

All Articles