有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

Java,集合上的多个迭代器,删除正确的子集和ConcurrentModificationException

我有一个集合a={(1,2),(1,2,3),(2,3,4),(3,4),(1)}

我想把它变成A={(1,2,3),(2,3,4)},从这个集合中去掉适当的子集

我使用一个HashSet来实现这个集合,使用2迭代器来运行这个集合,并使用containsAll(c)检查所有对的正确子集条件,使用remove()方法来删除正确的子集

代码如下所示:

HashSet<Integer> hs....
Set<Integer> c=hs.values();
Iterator<Integer> it= c.iterator();
while(it.hasNext())
{
    p=it.next();
    Iterator<Integer> it2= c.iterator();
    while(it2.hasNext())
    {
        q=it2.next();
        if q is a subset of p
            it2.remove();
        else if p is a subset of q
        {
            it.remove();
            break;
        }
    }
}

我第一次从内部while循环中出来并执行

p=it.next();

当在集合上迭代时修改集合时会出现异常。但这就是问题所在。remove()用于

我在仅使用1个迭代器时使用了remove(),在那里没有遇到任何问题

如果异常是因为我在迭代时从“c”或“hs”中删除了一个元素,那么当它遇到下一个元素时,应该抛出异常。next()命令,但我没有看到它。我看到它时,它遇到了它。next()命令

我使用了调试器,在删除元素后,集合和迭代器处于完美的顺序。它们包含并指向正确的更新集和元素。信息技术next()包含要分析的下一个元素,它不是已删除的元素

关于如何在提交更新之前不复制hashset本身并将其用作中介的情况下执行我正在尝试的操作,有什么想法吗

多谢各位


共 (4) 个答案

  1. # 1 楼答案

    ConcurrentModificationException背后的思想是维护迭代器的内部状态。当您从一组项目中添加或删除内容时,即使没有出现任何错误,它也会引发异常。这是为了避免编码错误,这些错误最终会在平常的代码中抛出NullPointerException。除非您有非常有限的空间限制或有一个非常大的集合,否则您应该只制作一个工作副本,您可以在其中添加和删除而不必担心

  2. # 2 楼答案

    无法使用it2修改集合,并继续使用it对其进行迭代。正如异常所说,它是并发修改,不受支持

    恐怕你只能选择中间系列了

    编辑

    实际上,您的代码似乎没有意义:您确定它是Integer的集合而不是Set<Integer>的集合吗?在您的代码中pqInteger,因此“如果q是p的子集”似乎没有太多意义

    有一个明显的方法可以让这一点变得更聪明:首先按大小对集合进行排序,当你从最大的集合到最小的集合时,将你想要保留的集合添加到一个新的列表中。您只需对照keep列表检查每个集合,而不必检查整个原始集合

  3. # 3 楼答案

    创建另一个包含要删除的所有子集的集合subsetNeedRemoved如何?对于每个子集,如果有适当的超集,则将子集添加到subsetNeedRemoved。最后,可以在subsetNeedRemoved上循环,并删除原始集中的相应子集

  4. # 4 楼答案

    我会写这样的东西

    PriorityQueue<Set<Integer>> queue = new PriorityQueue<Set<Integer>>(16, 
     new Comparator<Set<Integer>>() {
      public int compare(Set<Integer> a, Set<Integer> b) {
        return b.size() - a.size(); // overflow-safe!
      }
    });
    queue.addAll(sets); // we'll extract them in order from largest to smallest
    List<Set<Integer>> result = new ArrayList<>();
    while(!queue.isEmpty()) {
      Set<Integer> largest = queue.poll();
      result.add(largest);
      Iterator<Set<Integer>> rest = queue.iterator();
      while(rest.hasNext()) {
        if(largest.containsAll(rest.next())) {
          rest.remove();
        }
      }
    }
    

    是的,它会消耗一些额外的内存,但它是惯用的、直截了当的,并且可能比另一种方法更快