简体   繁体   中英

Why does my loop for values inside a HashMap stop?

I am trying to loop through available slot capacity within a HashMap. The part until the second else works as intended.

        int preferredSlot = 0;
        int numberOfSlots = 3;
        int capacityPerSlot = 3;
        HashMap<Integer, Integer> slots = new HashMap<Integer, Integer>();
        int givenSlot = 100, count = 0;

        if (slots.size() < (numberOfSlots + 1) * (capacityPerSlot + 1)) {
            if (!slots.containsValue(preferredSlot)) {
                givenSlot = preferredSlot;
                slots.put(count, preferredSlot);
                count++;
            } else {
                int valueCount = 0;
                for (Object value : slots.values()) {
                    if (value.equals(preferredSlot)) {
                        valueCount++;
                    }
                }
                if (valueCount <= capacityPerSlot) {
                    givenSlot = preferredSlot;
                    slots.put(count, preferredSlot);
                    count++;
                } else {
                    int valueCount2 = 0;
                    int i = 1;
                    for (Object value : slots.values()) {
                        if (value.equals(preferredSlot + i)) {
                            valueCount2++;
                            System.out.println("i=" + i + "  count=" + valueCount2);
                            if (valueCount2 > capacityPerSlot) {
                                valueCount2 = 0;
                                i++;
                                System.out.println("i2=" + i + "  count2=" + valueCount2);     
                            }
                        }
                    }
                    if (valueCount2 <= capacityPerSlot) {
                        givenSlot = preferredSlot + i;
                        slots.put(count, i);
                        count++;
                    }
                }
            }
        }
        System.out.println("Given Slot: "+givenSlot);
    }
}

I am only having problems with this loop:

} else {
                    int valueCount2 = 0;
                    int i = 1;
                    for (Object value : slots.values()) {
                        if (value.equals(preferredSlot + i)) {
                            valueCount2++;
                            System.out.println("i=" + i + "  count=" + valueCount2);
                            if (valueCount2 > capacityPerSlot) {
                                valueCount2 = 0;
                                i++;
                                System.out.println("i2=" + i + "  count2=" + valueCount2);     
                            }
                        }
                    }
                    if (valueCount2 <= capacityPerSlot) {
                        givenSlot = preferredSlot + i;
                        slots.put(count, i);
                        count++;
                    }

If I insert these test numbers into my map, there's only supposed to be 1 capacity left for slot 3.


        slots.put(100, 0);
        slots.put(101, 0);
        slots.put(102, 0);
        slots.put(122, 0);

        slots.put(103, 1);
        slots.put(104, 1);
        slots.put(105, 1);
        slots.put(120, 1);

        slots.put(106, 2);
        slots.put(107, 2);
        slots.put(108, 2);
        slots.put(121, 2);

        slots.put(110, 3);
        slots.put(111, 3);
        slots.put(112, 3);

But my console output looks like this:

i=1  count=1
i=1  count=2
i=1  count=3
i=1  count=4
i2=2  count2=0
i=2  count=1
Given Slot: 2

Why does my loop through the values stop at this point? The count is supposed to go up to 4 and then increment i to 3. Afterwards the count should go up to 3 and finally my givenSlot should be 3. What am I doing wrong with this loop?

Note that the values are iterated in no particular order. Do not expect the for loop to encounter them in the order in which you inserted them into the map.

Here:

for (Object value : slots.values()) {
    if (value.equals(preferredSlot + i)) {

You are filtering out the values that doesn't equal preferredSlot + 1 , so if a value is not preferredSlot + 1 , it will not be checked again . However, those values need to be checked again when i changes!

The loop stops because all the values in the map has been iterated through, once . When i was 1, you ignored a few 2's in the map. Now that i is 2, you don't actually encounter those 2's again, because the for loop only loops through the values once .

One way to fix this is to use a nested loop. The outer loop will repeat the for (Integer value: slots.values()) loop. You can move the int i; and i++; statements into the outer loop header. The stopping condition would be when the map definitely does not contain the value preferredSlot + i - when preferredSlot + i is greater than numberOfSlots .

int i;
boolean found;
for (i = 0; preferredSlot + i <= numberOfSlots; i++) {
  found = true;
  for (Integer value : slots.values()) {
    if (value.equals(preferredSlot + i)) {
      valueCount2++;
      System.out.println("i=" + i + "  count=" + valueCount2);
      if (valueCount2 > capacityPerSlot) {
        valueCount2 = 0;
        found = false;
        break; // reached capacity
      }
    }
  }
  if (found) { // if this is true, we have never reached the first break
    break;
  }
}
if (valueCount2 <= capacityPerSlot) {
  givenSlot = preferredSlot + i;
  slots.put(count, i);
  count++;
}

Alternatively, use a little bit of streams to get the given slot:

int preferredSlot = 0;
int numberOfSlots = 3;
int capacityPerSlot = 3;
HashMap<Integer, Integer> slots = new HashMap<Integer, Integer>();

// put the values in...

int count = 0;

OptionalInt givenSlot = IntStream.rangeClosed(preferredSlot, numberOfSlots).filter(slotNumber ->
    slots.values().stream().filter(existingSlot -> existingSlot == slotNumber).count() <= numberOfSlots
).findFirst();

// This appears to be what you want to ultimately do...
givenSlot.ifPresent(slot -> {
  slots.put(count, slot);
  System.out.println("Given Slot: "+ slot);
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM