Reputation: 1925
I have a set multimap that stores some strings against a month(integer).
MonthlyCount = {1:["hello"],2:["hello","hi"]}
I have a map that counts the number of strings per month and adds them. I use containsKey filter to check if the key is present in the collection, and add them to the map.
final String[] months = new DateFormatSymbols().getShortMonths();
final Map<String, Object> metaData = new LinkedHashMap<>();
private SetMultimap<Integer, String> MonthlyCount;
for (int i = 0; i <= month; i++) {
final int count = MonthlyCount.containsKey(i + 1) ? MonthlyCount.get(i + 1).size() : 0;
metaData.put(months[i], count);
}
Is there a way to achieve the same behavior with Java8's streams and filters ?
Upvotes: 3
Views: 291
Reputation: 298103
Note that you are doing unnecessary work. Have look at SetMultimap.get
:
Returns a view collection of the values associated with
key
in this multimap, if any. Note that whencontainsKey(key)
is false, this returns an empty collection, notnull
.
So all you need to do in your loop, is
metaData.put(months[i], MonthlyCount.get(i + 1).size());
as it will be zero for absent keys anyway. If you have a non-guava Map<…,Set<…>>
, you could do an equivalent operation in Java 8:
metaData.put(months[i], MonthlyCount.getOrDefault(i + 1, emptySet()).size());
where emptySet()
is a static import of Collections.emptySet()
.
I wouldn’t rewrite the loop to use a stream when you want to add to an existing Map
. After all, the code is concise enough
for(int i=0; i<month.length; i++)
metaData.put(months[i], MonthlyCount.get(i + 1).size());
and won’t become better with a stream…
Upvotes: 4
Reputation: 393771
You can use an IntStream
to iterate over the required range and use Collectors.toMap
to produce the required map :
Map<String,Integer> map =
IntStream.range(0,months.length)
.boxed()
.collect(Collectors.toMap(i->months[i],
i->MonthlyCount.containsKey(i + 1) ? MonthlyCount.get(i + 1).size() : 0));
Upvotes: 5