Vishal Anand
Vishal Anand

Reputation: 178

Best way to replace multiple FOR loops with stream api in Java

I want to make this function run is less time. I am assuming stream() might help. But not sure how.

private List<TodayMenu> getRecommendedTodayMenuItems(Map<String, Integer> itemsGroupedDailySales, List<TodayMenu> itemsOnTodayMenu) {

    List<TodayMenu> recommendedTodayMenu = new ArrayList<>();

    for (Map.Entry<String,Integer> itemGroupedDailySales : itemsGroupedDailySales.entrySet()) {
        for (TodayMenu todayMenu : itemsOnTodayMenu) {
            if (todayMenu.getMenuId().equals(itemGroupedDailySales.getKey())) {
                recommendedTodayMenu.add(todayMenu);
                break;
            }
        }
        if (recommendedTodayMenu.size() >= 9) {
            return recommendedTodayMenu;
        }
    }
    return recommendedTodayMenu;
}

Upvotes: 4

Views: 478

Answers (3)

Conffusion
Conffusion

Reputation: 4475

The result contains only records of itemsOnTodayMenu so you can start iterating over this list and perform a lookup in itemsGroupedDailySales (HashMap is good in this).

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

private List<TodayMenu> getRecommendedTodayMenuItemsBetter(Map<String, Integer> itemsGroupedDailySales,
        List<TodayMenu> itemsOnTodayMenu) {
    return itemsOnTodayMenu.stream()
        .filter((tm)->itemsGroupedDailySales.containsKey(tm.getMenuId()))
        .limit(9)
        .collect(Collectors.toList());
}

one remark: you don't use the values of itemsGroupedDailySales. Your logic stops after the first 9 matching items but there is no order defined. It is for example not the top most sold that are selected as recommended. I hope you are aware of this.

Upvotes: 3

Lajos Arpad
Lajos Arpad

Reputation: 76464

You intend to find a single element at most in the inner cycle from the outer cycle. So you need to map on the main structure, use filter to check the equals that you had and call findFirst to achieve the behavior with the break of your initial code. To limit the number of results, call the method with the same name.

I would write some code for this, but I am not experienced with Java stream and do not have the means to test whatever code I would write. So, please try implementing this idea and make sure to tell me how it goes.

Upvotes: 0

Cyril G.
Cyril G.

Reputation: 2017

You should index your itemsOnTodayMenu by id in a map. You can save time from O(n*m) to O(n+m).

  • iterate itemsOnTodayMenu to build the map
  • iterate itemsGroupedDailySales
    • get today menu by id from the map

Upvotes: 1

Related Questions