Vidurajith Darshana
Vidurajith Darshana

Reputation: 836

Java HashMap iterate through for each loop but all the values are same being the last value of a loop

I have a problem using Java HashMap API. I iterate through the loop and then insert key and values to the HashMap. I also check the values before insert to hashmap all exist correctly. after then I print the hashmap, there is same values are printed finally.but all are the last value of the above loop. Below is the code:-

    Map<String,Map<String,StockReOrderLevel>> stockReorderLevels = new HashMap<>();
    List<StockReOrderLevel> defaultStockItemList = db.findDefaultStockItem();
    List<String> orderedItemCodes=new ArrayList<>();
    Map<String, StockReOrderLevel> itemMap = new HashMap<>();

    defaultStockItemList.forEach(item-> {
        orderedItemCodes.add(item.getCode());
        itemMap.put(item.getCode(), item);
    });

    outletList.forEach(outletCode->{

        Map<String, StockReOrderLevel> clone = (Map<String, StockReOrderLevel>) ((HashMap<String, StockReOrderLevel>) itemMap).clone();
        List<OutletItem> lastStockTakenForOutlet = db.findLastStockTakenForOutlet(outletCode);

        if(lastStockTakenForOutlet!=null && !lastStockTakenForOutlet.isEmpty()){
            lastStockTakenForOutlet.forEach(outletItem -> {

                if (clone.containsKey(outletItem.getItemCode())) {
                    StockReOrderLevel stockReOrderLevel = clone.get(outletItem.getItemCode());
                    stockReOrderLevel.setReorderlevel(outletItem.getReorderLevel());
                    clone.put(outletItem.getItemCode(),stockReOrderLevel);
                }
            });

            //get database values
            Map<String,Object> paramMap=new HashMap<>();
            paramMap.put("outletCode",outletCode);
            paramMap.put("takenDate",lastStockTakenForOutlet.get(0).getTakenDate());
            List<ItemLevel> reOrderedLevelOutletItems=db.findTotalOrderdBottlesByOutlet(paramMap);

            //change the clone again
            if(reOrderedLevelOutletItems!=null && !reOrderedLevelOutletItems.isEmpty()){
                reOrderedLevelOutletItems.forEach(itemLevel -> {

                    if (clone.containsKey(itemLevel.getItemCode())) {

                        StockReOrderLevel stockReOrderLevel = clone.get(itemLevel.getItemCode());
                        stockReOrderLevel.setReorderlevel(stockReOrderLevel.getReorderlevel()+itemLevel.getAmount());

                        clone.put(itemLevel.getItemCode(),stockReOrderLevel);
                    }
                });
            }
        }

        //convert map and it gives the map correctly
        Map<String,StockReOrderLevel> idlOrdered= getIndexedItemOrder(orderedItemCodes,clone);

        //i printed values before add to parent map in here
        stockReorderLevels.put(outletCode, idlOrdered);
    });
    return stockReorderLevels;

Upvotes: 2

Views: 1161

Answers (2)

John Kim
John Kim

Reputation: 1158

When you get the last element repeating when printing after a for loop it's almost certainly due to not declaring new variables (and thus not new memory). For example :

    List <Integer[]> arrayOuter = new ArrayList <> ();
    Integer[] array = new Integer[] {1, 2, 3, 4};

    for (int i = 0; i < 4; i++) {
        //shuffle array    
        Collections.shuffle(Arrays.asList(array));

        //add array to arraylist
        arrayOuter.add(array);
    }

If the last result of the shuffle was {4, 2, 1, 3}, it would print {4, 2, 1, 3} 4 times because I declared the array being inserted once and therefore all elements are pointing to one array (and each iteration overwriting the previous iteration). The correct way would be to declare a new array in each iteration of the loop, like so :

    List <Integer[]> arrayOuter = new ArrayList <> ();


    for (int i = 0; i < 4; i++) {
        Integer[] array = new Integer[] {1, 2, 3, 4};
        //shuffle array    
        Collections.shuffle(Arrays.asList(array));

        //add array to arraylist
        arrayOuter.add(array);
    }

One other culprit I can think of is that your key, outletCode remains the same and you are overwriting your previous (key, value) every iteration of the loop.

Upvotes: 1

Vidurajith Darshana
Vidurajith Darshana

Reputation: 836

Finally the answer is resolved by @ThomasKläger. i insert the defaultStockItem into the loop and the edited code is here.

Map<String,Map<String,StockReOrderLevel>> stockReorderLevels = new HashMap<>();


outletList.forEach(outletCode->{

List<StockReOrderLevel> defaultStockItemList = db.findDefaultStockItem();
List<String> orderedItemCodes=new ArrayList<>();
Map<String, StockReOrderLevel> itemMap = new HashMap<>();

defaultStockItemList.forEach(item-> {
    orderedItemCodes.add(item.getCode());
    itemMap.put(item.getCode(), item);
});

    Map<String, StockReOrderLevel> clone = (Map<String, StockReOrderLevel>) ((HashMap<String, StockReOrderLevel>) itemMap).clone();
    List<OutletItem> lastStockTakenForOutlet = db.findLastStockTakenForOutlet(outletCode);

    if(lastStockTakenForOutlet!=null && !lastStockTakenForOutlet.isEmpty()){
        lastStockTakenForOutlet.forEach(outletItem -> {

            if (clone.containsKey(outletItem.getItemCode())) {
                StockReOrderLevel stockReOrderLevel = clone.get(outletItem.getItemCode());
                stockReOrderLevel.setReorderlevel(outletItem.getReorderLevel());
                clone.put(outletItem.getItemCode(),stockReOrderLevel);
            }
        });

        //get database values
        Map<String,Object> paramMap=new HashMap<>();
        paramMap.put("outletCode",outletCode);
        paramMap.put("takenDate",lastStockTakenForOutlet.get(0).getTakenDate());
        List<ItemLevel> reOrderedLevelOutletItems=db.findTotalOrderdBottlesByOutlet(paramMap);

        //change the clone again
        if(reOrderedLevelOutletItems!=null && !reOrderedLevelOutletItems.isEmpty()){
            reOrderedLevelOutletItems.forEach(itemLevel -> {

                if (clone.containsKey(itemLevel.getItemCode())) {

                    StockReOrderLevel stockReOrderLevel = clone.get(itemLevel.getItemCode());
                    stockReOrderLevel.setReorderlevel(stockReOrderLevel.getReorderlevel()+itemLevel.getAmount());

                    clone.put(itemLevel.getItemCode(),stockReOrderLevel);
                }
            });
        }
    }

    //convert map and it gives the map correctly
    Map<String,StockReOrderLevel> idlOrdered= getIndexedItemOrder(orderedItemCodes,clone);

    //i printed values before add to parent map in here
    stockReorderLevels.put(outletCode, idlOrdered);
});
return stockReorderLevels;

Upvotes: 0

Related Questions