迭代集合 - 删除其他元素

时间:2016-04-22 20:40:07

标签: java collections iterator

如果我现在不仅要删除元素我的迭代点,还要删除另一个元素,我该怎么办?任务是写出总和达到某个值的对(它们存储在HashSet集中)。想法:遍历集合,找到总和到我需要的第二个元素,将它们写出并从集合中删除。我的意思是,如果我的集合是:[1,2,3]和int sum = 4,那么我迭代,找到元素1st:1,检查4 - 1 = 3,写出(1,3),然后我想从集合中删除1和3,以便只剩下{2}。我当然不能这样做:

while (itr.hasNext()) {
  int elem = itr.next();
  int toSum = sum - elem;
  if (set.contains(toSum)) {
    System.out.println("(" + elem + "," + toSum + ")");
  }
  itr.remove();
  set.remove(toSum);
}

因为并发异常。我找到了解决方案:

while (itr.hasNext()) {
  HashSet<Integer> notNeeded = new HashSet<Integer>();
  int elem = itr.next();
  if (notNeeded.contains(elem)) {
    itr.remove();
  }
  else {
    int toSum = sum - elem;
    if (set.contains(toSum)) {
      System.out.println("(" + elem + "," + toSum + ")");
      notNeeded.add(toSum);
    }
    itr.remove();
  }
}

但这看起来并不优雅和高效(特别是节省空间)。有没有更好的方法呢?

2 个答案:

答案 0 :(得分:1)

我建议使用已使用值的第二个Set。然后,您可以决定是否在最后从原始集中删除它们。

Set<Integer> set = new HashSet<>(Arrays.asList(1,2,3,4,5,6));
int target = 7;

Set<Integer> used = new HashSet<>();
for (Integer value1 : set) {
    if (used.contains(value1))
        continue; // already processed
    Integer value2 = target - value1;
    if (! value2.equals(value1) && set.contains(value2)) {
        used.add(value1);
        used.add(value2);
        System.out.println("(" + value1 + "," + value2 + ")");
    }
}
set.removeAll(used); // optional

通过使其具有非破坏性,您可以将Set重新用于其他搜索:

private static void listPairs(Set<Integer> set, int target) {
    System.out.print(target + ": ");
    Set<Integer> used = new HashSet<>();
    for (Integer value1 : set)
        if (! used.contains(value1)) {
            Integer value2 = target - value1;
            if (! value2.equals(value1) && set.contains(value2)) {
                used.add(value1);
                used.add(value2);
                System.out.print("(" + value1 + "," + value2 + ")");
            }
        }
    System.out.println();
}
public static void main(String[] args) {
    Set<Integer> set = new HashSet<>(Arrays.asList(1,2,3,4,5,6));
    listPairs(set, 7);
    listPairs(set, 6);
    listPairs(set, 5);
}

<强>输出

7: (1,6)(2,5)(3,4)
6: (1,5)(2,4)
5: (1,4)(2,3)

答案 1 :(得分:0)

当然,由于并发异常,您无法在Set.remove()内调用Iterator,但您可以中断迭代并在之后将其删除。

Integer toSumFound = null;
while (itr.hasNext()) {
    int elem = itr.next();
    int toSum = sum - elem;
    if (set.contains(toSum)) {
      toSumFound = toSum;
      System.out.println("(" + elem + "," + toSum + ")");
      itr.remove();
      break;
    }
}
set.remove(toSumFound); //Check for nulls if needed