Вопрос

Is there a way to regroup guava multimap elements. For example let's assume that we have this multimap :

Multimap<String, Integer> testMultimap = ArrayListMultimap.create();
testMultimap.put("key1", 15);
testMultimap.put("key2", 12);
testMultimap.put("key1", 20);

And we want to get the sum of every multimap's key elements. So is there a guava way to handle this and get a simple result map like this :

resultMap => "Key1": 35, "Key2": 12

Thanks in advance.

Это было полезно?

Решение 2

I find it, i could do it like this :

Function<Collection<Integer>, Number> additionFunction = new Function<Collection<Integer>, Number>() {
    @Override
    public Number apply(Collection<Integer> numbers) {
        int sum = 0;
        for (Integer number : numbers) {
            sum += number; 
        }
        return sum;
    }
};

Maps.transformValues(testMultimap.asMap(), additionFunction);

PS : The advantage of using the guava way here, is that we could define multiple functions and then switch between them easily throw the interface Function<Collection<Integer>, Number>.

Другие советы

Looks like you're using wrong collection in first place - instead of Multimap you should use Multiset. From Guava Wiki:

Guava provides a new collection type, Multiset, which supports adding multiples of elements. Wikipedia defines a multiset, in mathematics, as “a generalization of the notion of set in which members are allowed to appear more than once...In multisets, as in sets and in contrast to tuples, the order of elements is irrelevant: The multisets {a, a, b} and {a, b, a} are equal.”

There are two main ways of looking at this:

  • This is like an ArrayList<E> without an ordering constraint: ordering does not matter.
  • This is like a Map<E, Integer>, with elements and counts.

With Multiset your example will be:

Multiset<String> bag = HashMultiset.create();
bag.add("key1", 15);
bag.add("key2", 12);
bag.add("key1", 20);

And then bag will contain 35 occurences of "key1" and 12 occurences of "key2", i.e. bag.toString() will be { key1 x 35, key2 x 12 }. (Use LinkedHashMultiset if you want preserve order of keys).

Each key of the Multimap yields a collection, so you can iterate over it, get the sum of the elements and put that in another map.

I haven't tested because I don't have the Apache Common library at hand, but something similar should work.

HashMap<String, Integer> resultMap = new HashMap<String, Integer>();

    Set<String> keys = testMultiMap.keySet();
    for(String key : keys){
        Collection<Integer> coll = (Collection<Integer>) testMultiMap.get(key);
        int sum = 0;
        for(Integer i : coll){
            sum += i;
        }
        resultMap.put(key, sum);
    }

According to the javadoc : http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ArrayListMultimap.html, I'm not sure that there is another way ti initialize your map.

But you can do somthing with this :

static final Map<String, Integer> testMap  = ImmutableMap.of(
        "key1", 15,
        "key2", 12
);
public static void main(String[] args) {

Multimap<String, Integer> data = ArrayListMultimap.create();
data.put("Alex", 10);
data.put("Tom", 20);
data.put("sirmagid", 30);
data.put("sirmagid", 31);

HashMap<String, Integer> resultMap = new HashMap<String, Integer>();

Set<String> keys = data.keySet();
for(String key : keys){
    Collection<Integer> coll = (Collection<Integer>) data.get(key);
    int sum = 0;
    for(Integer i : coll){
        sum += i;
    }
    resultMap.put(key, sum);
}


for (Map.Entry entry : resultMap.entrySet())
{    
System.out.println("key: " + entry.getKey() + "; value: " + entry.getValue());
}

lib google guava

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top