Same values for every key in hashmap

2019-07-15 02:06发布

问题:

I'll start with my code

 public void simulateSale(List<IceCream> dailyIceCreamStock) {
    date = LocalDate.now().minusDays(6);
    DateTimeFormatter fmt = DateTimeFormat.forPattern("yyyy-MM-dd");

    for (int i = 0; i < timeInterval; i++) {
        for(IceCream iceCream: dailyIceCreamStock){
            iceCream.setSoldCount(rand.nextInt(IceCream.AMOUNT + 1));
            iceCream.setStockDate(date);
        }

        //Every day should have different ArrayList of values
        this.weeklyStats.put(date.toString(fmt), dailyIceCreamStock);
        date = date.plusDays(1);
    }

Problem is on this line: this.weeklyStats.put(date.toString(fmt), dailyIceCreamStock);

As you can see, I'm adding randomly generated values to the hashmap of type:

Map<String, List<IceCream>> weeklyStats

Problem is, that when I iterate this hashmap, every key has the same List of value. Output looks like this:

[11, 3, 11, 12, 20]
[11, 3, 11, 12, 20]
[11, 3, 11, 12, 20]
[11, 3, 11, 12, 20]
[11, 3, 11, 12, 20]
[11, 3, 11, 12, 20]
[11, 3, 11, 12, 20]

Desired output is to have random values in every of this list. I guess, there's some problem with scope, which I don't understand

回答1:

You are adding the same List instance multiple times to the Map. You should create copies of the List in order to have distinct values in your Map :

for (int i = 0; i < timeInterval; i++) {
    List<IceCream> copy = new ArrayList<>(dailyIceCreamStock); // create a copy
    for(IceCream iceCream: copy){ // modify the elements of the copy
        iceCream.setSoldCount(rand.nextInt(IceCream.AMOUNT + 1));
        iceCream.setStockDate(date);
    }

    //Every day should have different ArrayList of values
    this.weeklyStats.put(date.toString(fmt), copy); // put the copy in the Map
    date = date.plusDays(1);
}

EDIT:

Actually, that's not enough, you should create copies of the IceCream instances too. Otherwise all Lists will be different instances, but the would still contain the same IceCream objects.

for (int i = 0; i < timeInterval; i++) {
    List<IceCream> copy = new ArrayList<>();
    for(IceCream iceCream: dailyIceCreamStock){ 
        IceCream newIC = new IceCream(); // not sure if you want to copy any
                                         // data from the original IceCream
        newIC.setSoldCount(rand.nextInt(IceCream.AMOUNT + 1));
        newIC.setStockDate(date);
        copy.add(newIC); // add a new IceCream instance to the new List
    }

    //Every day should have different ArrayList of values
    this.weeklyStats.put(date.toString(fmt), copy); 
    date = date.plusDays(1);
}


回答2:

Every iteration, you modify the same List<IceCream> dailyIceCreamStock, so all keys in your Map point to the same list.

You probably want to initialize and reference a new, deep-copy of your List at every iteration and put that in your Map instead, after the random mutations are performed.