Search code examples
javafunctional-programminghashmapjava-streamapache-commons

How to extract each column data?


Question 1: How to extract each column of data using the java functional programming?

Question 2 : How to extract each column of data and then put them into Map<Date, List<Integer>>?

Output of the data

The output shown in the screenshot above is print from List<List<String>> covidListWithoutCountryDetails

My try (but failed):

Map<String, List<String>> dateWithEachDayAmountCases= new HashMap<>();
        covidListWithoutCountryDetails
                .stream()
                .map(x-> dateWithEachDayAmountCases.put(covidListWithoutCountryDetails.get(0).get(0),zeroIndexList))
                .collect(Collectors.toList())
                        .forEach(x->System.out.println(x));

Desired output:

{2020/1/22=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}
{2020/1/23=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}
{2020/1/24=[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]}
...............
...............
...............
more and more until the end 

Solution

  • As the first row contains date headers, and the rest rows contain values, it may be worth to prepare a list of keys for the first "row", then a map containing empty array lists per key, and then populate the column data for each date.
    Note: using LocalDate instead of obsolete Date class

    List<List<String>> data = Arrays.asList(
        Arrays.asList("2020/12/31", "2021/01/01", "2021/02/01", "2021/03/01"),
        Arrays.asList("1",   "2",  "3",  "4"),
        Arrays.asList("10", "20", "30", "40"),
        Arrays.asList("20", "40", "60", "80")
    );
    
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
    
    List<LocalDate> keys = data.get(0).stream().map(s -> LocalDate.parse(s, formatter)).collect(Collectors.toList());
    
    Map<LocalDate, List<Integer>> map = new LinkedHashMap<>();
    
    IntStream.range(0, data.get(0).size())
        .forEach(i -> map.put(keys.get(i), new ArrayList<>()));
    
    data.stream()
        .skip(1)
        .forEach(row -> IntStream.range(0, row.size()) // iterate "columns" by index
            .forEach(i -> map.get(keys.get(i))
                        .add(Integer.parseInt(row.get(i)))
            )
        );
        
    System.out.println(map);
    

    Output:

    {2020-12-31=[1, 10, 20], 2021-01-01=[2, 20, 40], 2021-02-01=[3, 30, 60], 2021-03-01=[4, 40, 80]}
    

    However, Stream API does not look to be very appropriate for this task, and good old for loops could be used instead.