2

I have a class like this.

public class Foo {
    private String prefix;
    private String sector;
    private int count;
}

Given a foo list:

//Args: prefix, sector, count
fooList.add(new Foo("44",,"RowC", 1 ));
fooList.add(new Foo("1",,"Rowa", 1 ));
fooList.add(new Foo("1",,"RowB", 1 ));
fooList.add(new Foo("1",,"Rowa", 1 ));

And I need to return the request an object sorted by Prefix asc like this:

{
  "1": {
    "Rowa": "2",
    "RowB": "1"
  },
  "44": {
    "RowC": "1"
  }
}

So the problem is: I have to group the list by the prefix, and then show, every sector and the count(*) of items on the list with the same row and sector. The far that I got is using stream like this:

fooList.stream()
       .collect(Collectors.groupingBy(
                Foo::getPrefix,
                Collectors.groupingBy(
                        Foo::getSector,
                        Collectors.mapping(Foo::getSector , Collectors.counting())
                )
        ));

The problem is, that the code above, is that the count is a Long, and I need to return as a String. I've tried with .toString but it gives me an error (Can assign java.lang.String to java.util.stream.Collector).

UPDATE

With the help of Andreas and Naman, now I can map count as String. I just need it sorted by Prefix.

Can anyone help me?

3
  • Performing Collectors.counting().toString() would have type String and putting that in a place where Collector is expected would throw a compile time error. Using Collectors.collectingAndThen(Collectors.counting(), String::valueOf) would help you there. Commented Mar 20, 2020 at 3:47
  • Tks, Naman. How can I get it sorted by the PREFIX? Commented Mar 20, 2020 at 11:15
  • @ErickDeMirandaOliveira - Let me know if my answer was helpful. Commented Mar 23, 2020 at 6:17

2 Answers 2

2

You were almost there, just replace the Collectors.mapping line with:

Collectors.summingInt(Foo::getCount))

As in:

List<Foo> fooList = new ArrayList<>();
fooList.add(new Foo("44", "RowC", 1 ));
fooList.add(new Foo("1", "Rowa", 1 ));
fooList.add(new Foo("1", "RowB", 1 ));
fooList.add(new Foo("1", "Rowa", 1 ));

Map<String, Map<String, String>> result = fooList.stream().collect(
        Collectors.groupingBy(
                Foo::getPrefix,
                TreeMap::new, // remove if prefix sorting not needed
                Collectors.groupingBy(
                        Foo::getSector,
                        () -> new TreeMap<>(Collator.getInstance()), // remove if sector sorting not needed
                        Collectors.collectingAndThen(
                                Collectors.summingInt(Foo::getCount),
                                String::valueOf
                        )
                )
        )
);

System.out.println(result); // prints: {1={Rowa=2, RowB=1}, 44={RowC=1}}

Notice the TreeMap constructors added to the groupingBy() calls, which ensures that the maps are sorted. The first is sorting lexicographically, while the second sorts according to spoken language, i.e. upper- vs lowercase doesn't affect order.

Sign up to request clarification or add additional context in comments.

6 Comments

hi Andreas. But now it returns a Integer instead Long. What I need is the count return as a STRING. Just notice that I forgot the ' " ' on my questions. I'll edit. Can you still help me ?
@ErickDeMirandaOliveira Ok, changed summed count value to be String
Tks brow!! You save my life
one last question. How can I get it sorted by the PREFIX?
@ErickDeMirandaOliveira Its good to make such edits(updates) to the question instead of comments. And do note that Collectors.counting would differ from Collectors.summingInt(Foo::getCount), it just happens that the input has the value of count set as 1 in the current example where both of them result in the same total count.
|
0

Is this what you need?

Code :

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.summingInt;

public class Main {
    public static void main(String [] args){
        List<Foo> fooList = new ArrayList<>();
        fooList.add(new Foo("44", "RowC", 1 ));
        fooList.add(new Foo("1", "Rowa", 1 ));
        fooList.add(new Foo("1", "RowB", 1 ));
        fooList.add(new Foo("1", "Rowa", 1 ));

        Map<String, Map<String, Integer>> result = grouper(fooList);
        result.forEach( (k,v) -> System.out.printf("%s\n%s\n", k,v) );
    }

    /* group the list by the prefix, and then show, every sector and the
    *  count(*) of items on the list with the same row and sector.*/
    public static Map<String, Map<String, Integer>> grouper(List<Foo> foos){
        //Map<prefix, Map<sector, count>
        Map<String, Map<String, Integer>> result = foos.stream()
                .collect(
                        //Step 1 - group by prefix. Outer map key is prefix.
                        groupingBy( Foo::getPrefix,
                                //Use a tree map which wil be sorted by its key, i.e prefix.
                                TreeMap::new,
                                //Step 2 - group by sector.
                                groupingBy( Foo::getSector,
                                        //Step 3 - Sum the Foo's in each sector in each prefix.
                                        summingInt(Foo::getCount)
                                )
                        )
                );
        return result;
    }

}

Output :

1
{Rowa=2, RowB=1}
44
{RowC=1}

PS - I referred to this tutorial to answer your question. I referred to the examples in "2.5. Grouping by Multiple Fields" and "2.7. Getting the Sum from Grouped Results". The next step was to find out how to also order by the key of a map while grouping which I got from "2.11. Modifying the Return Map Type" and also checked it here.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.