Reputation: 99
I have a hash structure hash_feat <String, List<String>>
where my keys are Years and the values list inside has a list of different terms.
I already have my hash has in a way that all items from a specific key are in the same list for that key, like:
<1997> <A,B,C,A,A,A,B,C,C,E>
<2003> <C,C,C,A,B,A,D,D,D,A>
<2004> <A,C,C,X,X,A,K,T,T,T>
I would like to have for each item a counting. For 1997 A:4, B:2, C:3, E:1 so on and so forth for the other keys.
I am trying to come up with this to use this "counting" to later display in a figure where I can visualize the highest counts for each item in a graph. Probably this is not the smartest way, so any advice here would be welcome as well.The idea is to have the quantity of each item in my list so I can manipulate/use in other methods.
Anyone have a good advice to do this in a smart way?
Upvotes: 4
Views: 424
Reputation: 6686
There is a data structure in Eclipse Collections called BagMultimap
that would would work well with your use case. Here is how to leverage MutableBagMultimap
with your example data.
MutableBagMultimap<String, String> multimap = Multimaps.mutable.bag.empty();
multimap.putAll("1997", Lists.mutable.with("A","B","C","A","A","A","B","C","C","E"));
multimap.putAll("2003", Lists.mutable.with("C","C","C","A","B","A","D","D","D","A"));
multimap.putAll("2004", Lists.mutable.with("A","C","C","X","X","A","K","T","T","T"));
Assert.assertEquals(4, multimap.get("1997").occurrencesOf("A"));
Assert.assertEquals(2, multimap.get("1997").occurrencesOf("B"));
Assert.assertEquals(3, multimap.get("1997").occurrencesOf("C"));
Assert.assertEquals(1, multimap.get("1997").occurrencesOf("E"));
You can output the multimap simply using forEachKeyMultivalues
and toStringOfItemToCount
.
multimap.forEachKeyMultiValues((key, values) ->
System.out.println("<" + key + "> " + ((Bag<String>)values).toStringOfItemToCount()));
This code displays the following:
<1997> {E=1, A=4, B=2, C=3}
<2004> {T=3, A=2, C=2, X=2, K=1}
<2003> {D=3, A=3, B=1, C=3}
Or you can write the following using forEachWithOccurrences
in order to control the output.
multimap.forEachKey(key -> {
System.out.print(key + " ");
multimap.get(key).forEachWithOccurrences((value, occurrences) ->
System.out.print(value + ":" + occurrences + " "));
System.out.println();
});
This code displays the following:
1997 E:1 A:4 B:2 C:3
2004 T:3 A:2 C:2 X:2 K:1
2003 D:3 A:3 B:1 C:3
Lastly, you can use topOccurrences
if you'd like the output ordered from greatest occurrences to least.
multimap.forEachKey(key -> {
System.out.print(key + " ");
MutableBag<String> bag = multimap.get(key);
bag.topOccurrences(bag.sizeDistinct())
.each(pair ->
System.out.print(pair.getOne() + ":" + pair.getTwo() + " "));
System.out.println();
});
This code displays the following:
1997 A:4 C:3 B:2 E:1
2004 T:3 A:2 C:2 X:2 K:1
2003 D:3 A:3 C:3 B:1
Note: I am a committer for Eclipse Collections
Upvotes: 4
Reputation: 16142
Here's a "simple" solution for Java 8:
import static java.util.stream.Collectors.*;
Map<String, Map<String, Long>> props =
map.entrySet().stream().collect(toMap(Map.Entry::getKey,
e -> e.getValue().stream().collect(groupingBy(String::toString, counting()))));
This will give you a Map of years to a Map of keys to counts.
Upvotes: 2
Reputation: 937
Hope currently you have something like :
Map<String,List<String>> map = new HashMap<>();
So you can iterate very through all the keys and get count for each key as below:
for (List<String> values : map.values()){
System.out.println(values.size());
}
If you need the count of each type within key then you have to check type using values.get() and count each type.
Upvotes: 0