Java streams generating map issue
I am working on a framework where we are trying to convert our traditional loops to streams. My problem is that I wrote two separate logics to get the price and colors, but I would like to combine them together so that they are presentable
Code for getting price values
List<Double> productPrices = product.getUpcs()
.stream()
.map(e -> e.getUpcDetails().getPrice().getRetail().getPriceValue())
.distinct()
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());
Code for getting flowers at prices
product.getUpcs()
.stream()
.filter(e -> e.getUpcDetails().getPrice().getRetail().getPriceValue() == 74.5)
.flatMap(e -> e.getUpcDetails().getAttributes().stream())
.filter(e2 -> e2.getName().contentEquals("COLOR"))
.forEach(e3 -> System.out.println(e3.getValues().get(0).get("value")));
I calculated the price in the above section to get the colors, instead I would like to get this as input from a list of price values ββand get the result in
Map<Double,List<colors>
output Map<75.4, {blue,black,orange}>
I tried to combine these both with no success, any help would be appriciated.
source to share
I would suggest that you study this or a similar tutorial to get a little understanding of how it works.
The key to the solution is to become familiar with the functionality Collectors.groupingBy()
. As a side note, it also shows the best way to handle pricing information in Java.
But what you need to do is something like this:
Map<Double, Set<String>> productPrices = product
.stream()
.map(e -> e.getUpcDetails())
.collect(
Collectors.groupingBy(Details::getPrice,
Collectors.mapping(Details::getColors, Collectors.collectingAndThen(
Collectors.toList(),
(set) -> set
.stream()
.flatMap(Collection::stream)
.collect(Collectors.toSet())))
));
Since your question is a little unclear about the details of related classes, I adopted this simple class structure:
class Details {
private double price;
private List<String> colors;
double getPrice() { return price; }
List<String> getColors() { return colors; }
}
class Product {
private Details details;
Details getUpcDetails() { return details; }
}
``,
It would be possible to optimize the code above, but I specifically left the ability to filter and display colors in the card collector.
source to share
First, you can turn your second stream into a method that gets the List
products (assuming they are filtered / grouped by price) and converts it to List
colors:
List<Color> productsToColors(final List<Product> products) {
return products.stream()
.flatMap(e -> e.getUpcDetails().getAttributes().stream())
.filter(e2 -> e2.getName().contentEquals("COLOR"))
.map(e3 -> e3.getValues().get(0).get("value"))
.collect(toList());
}
You can use the groupingBy collection to collect all products at their price in List
, and then with a second create a second thread and the method productsToColors
gets the desired card:
Map<Double, List<Color>> colors = product.getUpcs().stream()
.collect(groupingBy(e -> e.getUpcDetails().getPrice().getRetail().getPriceValue())
.entrySet().stream()
.collect(toMap(Entry::getKey, e -> productsToColors(e.getValue())));
You can also groupingBy
create TreeMap
a color map to be sorted by price.
As a side note, beware of comparing double values ββfor such equality. You might want to round them up first. Or use long variables multiplied by 100 (i.e. Cents).
source to share