Home > Back-end >  From a stream operation, how do I map a set of values to anoter value?
From a stream operation, how do I map a set of values to anoter value?

Time:05-02

This is a modified Person class named CavePerson. It has no getters, but does have variables that correspond to indexes in a CSV/Excel file. Each CavePerson has a number, name, gender, and the year they were introduced in.

public class CavePerson {
   public final int num;
   public final String name;
   public final String gender;
   public final int intro_year;

   public CavePerson (int aNum, String aName, String aGender, int anIntro_year){
      this.num = aNum;
      this.name = aName;
      this.gender = aGender;
      this.intro_year = anIntro_year;
   }

   public static CavePerson lineValues(String line) {
      String array = line.split(",");
      int numA = array[0];
      String nameA = array[1];
      String genderA array[2];
      int intro_yearA = array[3];
      return new CavePerson(numA, nameA, genderA, intro_yearA);
   }
}

Each line in this cavepeople.csv file is a CavePerson object:

Num Name Gender Year
1 Fred Male 1960
2 Wilma Female 1960
3 Barney Male 1961
4 Betty Female 1961
5 Dino Male 1964
6 BamBam Male 1966
7 Puss Male 1967
8 Pebbles Female 1966

I am practicing streams, and I wanted to get a count of each gender that was introduced by each year. The expected result return a map of each year and list the number of male/female characters that were introduced that year. It should look like this:

1960, Male 1, Female 1

This is what I have so far. From a Stream, I map each year to the count of each gendered character, but I am getting a type error stating that I cannot convert Map<Object,Long> to my desired Map<Integer, Map<String,Long>>

Function<Stream<CavePerson>, Map<Integer, Map<String, Long>>> getGenderByYear = 
    e -> e.map(x -> x.year)
          .collect(Collectors.groupingBy((CavePerson-> CavePerson.gender), Collectors.counting()));

Am I missing something here?

CodePudding user response:

Your function takes an input as Stream<CavePerson>. So once you do the e.map(x -> x.year), the Stream is converted to Stream<Integer>. After this you cannot access the properties of the cave person object, because you have converted the stream to a different type. So what you had to do was:

  1. Group the stream by year.
  2. Within each year, do an additional grouping based on gender.
  3. Now apply the function to your list.

Note: assume static imports for Collectors.groupingBy and Collectors.counting():

Function<Stream<CavePerson>, Map<Integer, Map<String, Long>>> mapper
    = str -> str.collect(groupingBy(c -> c.year, 
                                    groupingBy(c -> c.gender, counting())));
  • Related