Iterate though the contents of a Map<String,List<Object>> and assign the values of the List<Object> into separate List<Double>

Viewed 73

I have a list of objects that contain coordinates and a name. An example of the printed list can be seen below:

[X=0.1, Y=0.1, name=Series1]
[X=0.1, Y=0.2, name=Series1]
[X=0.1, Y=0.3, name=Series1]
[X=0.1, Y=0.4, name=Series2]
[X=0.1, Y=0.5, name=Series2]

What I'm trying to achieve is to group them together based on the name which can be done with the following Java 8 operation:

Map<String, List<Coordinates>> newList = coordinateList.stream()
           .collect(Collectors.groupingBy(Coordinates::getName));

Output:

Series1=[[X=0.1, Y=0.1],[X=0.1, Y=0.2],[X=0.1, Y=0.3]]
Series2=[[X=0.1, Y=0.4],[X=0.1, Y=0.5]]

The final step which I have not yet been able to achieve, is to iterate through the Map, create lists of X's and Y's so I can finally create a graph (chart.addSeries(name, xData, yData);).

My approach to this so far has been the following:

    List<Double> xData = new LinkedList<Double>();      
    List<Double> yData = new LinkedList<Double>();

    newList.forEach((k, v) -> {
        //TO-DO
    });

Inside the loop I would like to assign X's and Y's to the corresponding lists but with no success so far.

One of the problems is that X and Y are associated with a Coordinates object, so I cannot just add them to the list which is of type Double. Another problem I faced is that I cannot get X and Y separately from the list. I have tried getX() and getY() but with no luck.

Example of what I would like the lists to contain:

For the key Series1 the generated lists would be the following:

xData=[0.1,0.1,0.1]
yData=[0.1,0.2,0.3]

For the next key Series 2:

xData=[0.1,0.1]
yData=[0.4,0.5]
2 Answers

In the forEach, (k, v) represents the key and the value of each pair, so you need to get the Coordinates and then its x and y. Also as you don't need specificly a LinkedList, use an ArrayList.

As you want a Series for each pair, your xData and yData should be in the loop :

for (Map.Entry<String, List<Coordinates>> serie : newList.entrySet()) {
    List<Double> xData = new ArrayList<>();
    List<Double> yData = new ArrayList<>();

    for (Coordinates coord : serie.getValue()) {
        xData.add(coord.getX());
        yData.add(coord.getY());
    }

    chart.addSeries(serie.getKey(), xData, yData);
}

Choose first option as it's easier to use, don't use forEach to quickly :

newList.forEach((key, value) -> {
    List<Double> xData = new ArrayList<>();
    List<Double> yData = new ArrayList<>();

    value.forEach(c -> {
        xData.add(c.getX());
        yData.add(c.getY());
    });

    chart.addSeries(key, xData, yData);
});

With Stream api you can move to :

newList.forEach((key, value) -> {
   List<Double> xData = value.stream().map(Coordinates::getX).collect(Collectors.toList());
   List<Double> yData = value.stream().map(Coordinates::getY).collect(Collectors.toList());
   chart.addSeries(key, xData, yData);
});

You can do it using collect iterating on Coordinate list as:

List<Double> xData = coordinateList.stream()
            .map(Coordinates::getX)
            .collect(Collectors.toCollection(LinkedList::new));

where coordinateList is List<Coordinate> as used previously for grouping and this is collecting to LinkedList as stated in the question OR you could do both the lists in a single iteration

coordinateList.forEach(coordinates -> {
    yData.add(coordinates.getY());
    xData.add(coordinates.getX());
});

Note: I've used coordinateList considering, it has not been altered pre or post the grouping statement as shared in the question.


You might though be looking for xData and yData series or each iteration and that might account for List<List<Double>> as output which can be achieved as :

List<List<Double>> xDatas = new ArrayList<>();
List<List<Double>> yDatas = new ArrayList<>();
newList.forEach((k,v) -> {
    xDatas.add(v.stream()
            .map(Coordinates::getX)
            .collect(Collectors.toCollection(LinkedList::new)));
    yDatas.add(v.stream()
            .map(Coordinates::getY)
            .collect(Collectors.toCollection(LinkedList::new)));
});
Related