为什么我的 HashMap 中的值循环会停止?

Why does my loop for values inside a HashMap stop?

我正在尝试遍历 HashMap 中的可用槽容量。直到第二个 else 的部分按预期工作。

        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);
    }
}

我只有这个循环有问题:

} 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++;
                    }

如果我将这些测试号码插入我的地图,插槽 3 应该只剩下 1 个容量。


        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);

但是我的控制台输出是这样的:

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

为什么我的值循环会在此时停止? count 应该增加到 4,然后将 i 增加到 3。之后计数应该增加到 3,最后我的 givenSlot 应该是 3。我做错了什么这个循环?

请注意,这些值没有按特定顺序迭代。不要指望 for 循环会按照您将它们插入地图的顺序遇到它们。

此处:

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

您正在过滤掉不等于 preferredSlot + 1 的值,因此如果值不等于 preferredSlot + 1将不会再次检查它 .但是,当 i 更改时,这些值 需要 再次检查!

循环停止,因为映射中的所有值都已迭代,一次。当 i 为 1 时,您忽略了地图中的几个 2。现在 i 是 2,你实际上不会再遇到那些 2,因为 for 循环只循环值 once.

解决这个问题的一种方法是使用嵌套循环。外循环将重复 for (Integer value : slots.values()) 循环。您可以将 int i;i++; 语句移动到外部循环 header 中。停止条件是当地图绝对不包含值 preferredSlot + i - 当 preferredSlot + i 大于 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++;
}

或者,使用一点流来获取给定的插槽:

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);
});