Is there a way to transform this into code a stream?

Viewed 57

There can't be any side effects in functional programming (stream), but I'm having trouble with that. I want to create a new object from values that I pick up along the way. I already have the Ship ship object and the Island buyIsland object and the objective is to calculate all possibilities from the list of List<String> cargoNames and the list of List<Island> sellIslands so that I can get the cargoSellPrice to make the profit calculation for that particular possibility.

The problem I'm facing is that I can't seem to have a way to get those values back once I map to create a new stream. Maybe I'm doing it wrong, but I can't seem to get it to work.

I need to have all 4 of those to create a new ProfitOption object:

new ProfitOption(buyIsland, cargoName, sellIsland, ship, levelOfDetail)

Obs: levelOfDetail is a default value

So, is there a way to convert the code below into a stream to make the code a bit more readable?

List<ProfitOption> profitOptions = new ArrayList<>();
Island buyIsland = islandCargoPriceDataTable.get(buyIslandName);
Collection<Island> islandList = islandCargoPriceDataTable.values();
Ship ship = shipPropertiesInfo.get(shipName);

Set<String> cargoList = buyIsland.getIslandCargoPrices().keySet();
for (String cargoName : cargoList) {
    int cargoBuyPrice = buyIsland.getIslandCargoPrices().get(cargoName).getPrice();
    for (Island sellIsland : islandList) {
        int cargoSellPrice = sellIsland.getIslandCargoPrices().get(cargoName).getPrice();
        if (cargoSellPrice > cargoBuyPrice) {
            profitOptions.add(new ProfitOption(
                    buyIsland, cargoName, sellIsland, ship, levelOfDetail));
        }
    }
}

The solution provided didn't really solve the problem, unfortunately. It seemed that it would work.

https://prnt.sc/T8tZ2sXAfrJc

1 Answers

You can create a stream over the cargoList and then generate a portion of ProfitOption objects by streaming over sellIsland and filtering cost-efficient prices.

Since every cargo in the cargoList can potentially produce multiple ProfitOption objects, in order to do transform a Stream<String> (where each element represents a cargo) into Stream<ProfitOption> you can use flatMap() operation.

That's how it might look like:

Collection<Island> islandList = // initialing buyIsland 
Set<String> cargoList =         // initialing cargoList
Island buyIsland =              // initialing buyIsland
Ship ship =                     // initialing ship

List<ProfitOption> profitOptions = cargoList.stream()
    .flatMap(cargoName -> islandList.stream()
        .filter(sellIsland -> sellIsland.getIslandCargoPrices().get(cargoName).getPrice()
                            > buyIsland.getIslandCargoPrices().get(cargoName).getPrice())
        .map(sellIsland -> 
                new ProfitOption(buyIsland, cargoName, sellIsland, ship, levelOfDetail))
        )
    ).toList(); // for Java 16 or collect(Collectors.toList()) for earlier versions
Related