-1

I have Multimap. Example:

00254=[00255, 2074E, 2074E, 2074E, 2074E, 2074E, 2074E, 00010, 00010, 00010, 0006, 0006, 0006, 00010, R01018, R01018, 0006, 0006, R01018, R01018, R01018, 12062, S2202962, S2202962, R01018, 12062, 20466, 12062, 20466, 22636, 20466, 20466, 22636, 22636, 22636, 22636, 22636, 22636, 22636, 22636, 00255, 2074E, 2074E, 2074E, 2074E, 2074E]
00256=[00257, 2074E, 2074E, 2074E, 2074E, 00010, 2074E, 2074E, 0006, 00010, 00010, 00010, 0006, 0006, 0006, R01018, R01018, 0006, R01018, R01018, R01018, 12062, S2202962, S2202962, R01018, 12062, 20466, 12062, 20466, 20466, 20466, 22636, 22636, 22636, 22636, 22636, 22636, 22636, 22636, 22636, 00257, 2074E, 2074E, 2074E, 2074E, 00010]

I want to get the number of value including duplicate value.

  • 00254=[00255:2, 2074E:11, 00010:4, 0006:5, R01018:6, ...]
  • 00256=[00257:2, 2074E:10, 00010:5, 0006:5, R01018:7, ...]

Is it possible to get duplicate number?

Thanks.

torochi
  • 11
  • 5
  • 3
    Everything is possible. Have you tried something, do you have something to show us ? And of course, can you explain what you try to check exactly. You speak about number value but I see `R01018` ... not a 10-based number. – AxelH Mar 22 '18 at 06:44
  • Thanks AxelH. I want to count the number of values. The type of data is not important. Any value can be. – torochi Mar 22 '18 at 06:53
  • Do you mean you want the count of values for a key, e.g. for key `00254` the count would be the sum of `2+11+4+5+6+...`? – Andreas Mar 22 '18 at 06:56
  • Per key, iterate the value and use a `Map` to count. But you need to try first. That "value" is nothing but a List, so you can simply use the same logic. See [Count occurrences of words in ArrayList](https://stackoverflow.com/q/5211194/4391450) – AxelH Mar 22 '18 at 06:57
  • Did you **read the documentation**, i.e. the javadoc of [`Multimap`](https://google.github.io/guava/releases/21.0/api/docs/com/google/common/collect/Multimap.html)? Perhaps `get(key).size()` is what you're looking for? – Andreas Mar 22 '18 at 06:58
  • @Andreas I think OP want to "group" on the value and do a count of occurrence. I think.... – AxelH Mar 22 '18 at 07:00
  • @Andreas get("00254").size() is 46. I want numbers for each. e. g. 00255 is 2, 2074E is 11. – torochi Mar 22 '18 at 07:02
  • @AxelH your right! – torochi Mar 22 '18 at 07:03

2 Answers2

4

Solution using Java 8 Stream to get the occurrence for a specific value, simply get the Collection for a value, then group on the value and count (using the Collectors function) to get a Map<String, Long> :

Multimap<Integer, String> maps =  ArrayListMultimap.create();
maps.put(1, "foo");
maps.put(1, "bar");
maps.put(1, "foo");
maps.put(2, "Hello");
maps.put(2, "foo");
maps.put(2, "World");
maps.put(2, "World");

Here is the idea to print the occurences per value :

maps.keySet().stream() //Iterate the `keys`
            .map(i -> i + " : " +  //For each key
                        maps.get(i).stream() //stream the values.
                            .collect( //Group and count
                                    Collectors.groupingBy(
                                            Function.identity(), 
                                            Collectors.counting()
                                    )
                            )
            )
            .forEach(System.out::println);

1 : {bar=1, foo=2}

2 : {Hello=1, foo=1, World=2}

This will generate a String, I let you adapt for your need.

AxelH
  • 14,325
  • 2
  • 25
  • 55
  • I use this code. `for (String key : multimap.keySet()) { qtyMap = multimap.get(key).stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); }` thanks. – torochi Mar 22 '18 at 07:23
3

Counting occurrences is a perfect use case for Multiset, which is

A collection that supports order-independent equality, like Set, but may have duplicate elements. A multiset is also sometimes called a bag.

Elements of a multiset that are equal to one another are referred to as occurrences of the same single element.

There are few different Multiset implementations you can choose from, and couple of handy set-like methods in Multisets helper class.

Here, you could either 1) collect to multiset or 2) use custom multimap with multiset values.

  1. Instead of grouping to map, you can collect an immutable multiset:

    ImmutableMultiset<String> qtyMultiset = multimap.get(key).stream()
        .collect(ImmutableMultiset.toImmutableMultiset());
    

    or mutable one:

    HashMultiset<String> qtyMultiset = multimap.get(key).stream()
        .collect(Multisets.toMultiset(Function.identity(), e -> 1, HashMultiset::create));
    
  2. Or maybe you can use custom multimap in the first place? (Unfortunately, there isn't any MultisetMultimap interface nor implementation, hence need for custom instance):

    Multimap<String, String> countingMultimap
        = Multimaps.newMultimap(new LinkedHashMap<>(), LinkedHashMultiset::create);
    

    You can drop Linked part if you don't need to preserve order. For your data:

    countingMultimap.putAll("00254", ImmutableList.of("00255", "2074E", "2074E", "2074E", "2074E", "2074E", "2074E", "00010", "00010", "00010", "0006", "0006", "0006", "00010", "R01018", "R01018", "0006", "0006", "R01018", "R01018", "R01018", "12062", "S2202962", "S2202962", "R01018", "12062", "20466", "12062", "20466", "22636", "20466", "20466", "22636", "22636", "22636", "22636", "22636", "22636", "22636", "22636", "00255", "2074E", "2074E", "2074E", "2074E", "2074E"));
    countingMultimap.putAll("00256", ImmutableList.of("00257", "2074E", "2074E", "2074E", "2074E", "00010", "2074E", "2074E", "0006", "00010", "00010", "00010", "0006", "0006", "0006", "R01018", "R01018", "0006", "R01018", "R01018", "R01018", "12062", "S2202962", "S2202962", "R01018", "12062", "20466", "12062", "20466", "20466", "20466", "22636", "22636", "22636", "22636", "22636", "22636", "22636", "22636", "22636", "00257", "2074E", "2074E", "2074E", "2074E", "00010"));
    

    returned multimap would be:

    {00254=[00255 x 2, 2074E x 11, 00010 x 4, 0006 x 5, R01018 x 6, 12062 x 3, S2202962 x 2, 20466 x 4, 22636 x 9], 00256=[00257 x 2, 2074E x 10, 00010 x 5, 0006 x 5, R01018 x 6, 12062 x 3, S2202962 x 2, 20466 x 4, 22636 x 9]}
    

For more information read Guava Wiki page about Multiset (which uses word count as an example).

Grzegorz Rożniecki
  • 27,415
  • 11
  • 90
  • 112