如何将HashMultiset <string>转换为Map <string,integer> </string,integer> </string>

时间:2014-01-13 14:45:31

标签: java collections guava

除了迭代HashMultiset<String>中的所有条目外,还有一些技巧可以将Map<String,Integer>转换为Set吗? 更新:整数应表示多集中字符串的计数。

5 个答案:

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

}

在我的实施中,我拒绝实施containsValuevalues方法,因为这些方法在上下文中没用。如果需要,可以通过循环访问条目并检查遇到的元素的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}