带有HashSet的java.util.ConcurrentModificationException [英] java.util.ConcurrentModificationException with HashSet

查看:54
本文介绍了带有HashSet的java.util.ConcurrentModificationException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在实现 Konrad Rudolph提出的算法.

我使用了 HashSet< Character>而不是使用C ++多重映射.[] []转换数组(这是家庭作业,无法使用Google的番石榴库).第一个维度是原始状态,第二个维度是命运状态,HashSet定义了在原始状态和命运状态之间转换的符号.我的Automaton类的构造函数是:

Instead of using a C++ multimap, I used a HashSet<Character> [][] transitions array (this is homework and Google's guava library cannot be used). The 1st dimension is the origin state, 2nd dimension is the destiny state and the HashSet defines the symbols for transition between origin and destiny states. The constructor for my Automaton class is:

Automaton (int numberOfStates)
{
    this.numberOfStates = numberOfStates;
    alphabet = new HashSet<>();
    finalStates = new HashSet<>();

    transitions = new HashSet[numberOfStates][numberOfStates];

    for (int i = 0; i < numberOfStates; i++)
    {
        for (int j = 0; j < numberOfStates; j++)
        {
            transitions[i][j] = new HashSet<Character>();
        }
    }
}

这是我使用以下转换数组实现的Konrad Rudolph算法:

This is my implementation of Konrad Rudolph's algorithm using this transitions array:

public String readStringInAutomaton (char[] inputString,
            int initialState)
{
    HashSet<Integer> currentStates = new HashSet<>();
    HashSet<Integer> nextStates = new HashSet<>();

    currentStates.add(initialState);

    // for each char in inputString
    for (int charIndex = 0; charIndex < inputString.length; charIndex++)
    {
        char currentTransitionChar = inputString[charIndex];
        // for each state in currentStates
        for (Integer originState : currentStates)
        {
            // for each transition starting from originState, current
            // char
            for (int destinyStateIndex = 0; destinyStateIndex < numberOfStates; destinyStateIndex++)
            {
                if (transitions[originState][destinyStateIndex]
                        .contains(currentTransitionChar))
                {
                    nextStates.add(destinyStateIndex);
                }
            }
        }
        currentStates = nextStates;
    }
}

我已尝试按照但是,当初始化转换时,我得到了一个java.lang.ArrayStoreException:java.util.Collections $ SynchronizedSet.

But then I get a java.lang.ArrayStoreException: java.util.Collections$SynchronizedSet when initializing transitions.

for (int i = 0; i < numberOfStates; i++)
{
    for (int j = 0; j < numberOfStates; j++)
    {
        transitions[i][j] = Collections
                .synchronizedSet(new HashSet<>());
    }
}

如何避免这些并发异常?

How can I avoid these Concurrency exceptions?

推荐答案

您的问题不是关于多线程的问题,而是关于在其中不断添加元素的 Set 进行迭代的问题.

Your problem is not about multithreading but about iterating over a Set in which you keep adding elements.

您具有 currentStates = nextStates ,然后在for循环 for(整数originState:currentStates)中,您执行 nextStates.add(destinyStateIndex)(而 nextStates currentStates 正在实现相同的实例!),而无需重新分配 nextStates .

You have currentStates = nextStates and then in your for loop for (Integer originState: currentStates) you do nextStates.add(destinyStateIndex) (while nextStates and currentStates are actualling the same instance!) without re-assigning nextStates.

您应该更正算法: nextStates 必须根据使用方式在循环中的某个位置重新分配.

You should correct your algorithm: nextStates must be re-assigned somewhere in the loop based on the way you use it.

这篇关于带有HashSet的java.util.ConcurrentModificationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆