Question

I am looking for a way to retrieve object from hashSet in Java. I did iteration over its elements like this:

for (Customer remainingNode : availableNodes) {
remainingNode.setMarginalGain(calculateMarginalGain(
                    remainingNode, seedSet, network, availableNodes,
                    churnNet));
}

Unfortunately due to concurrent modification Exception I have to change that to something like this:

for(int i=0;i<numberofRemainingNodes;i++){
Customer remainingNode=availableNodes.get(i);
remainingNode.setMarginalGain(calculateMarginalGain(
                        remainingNode, seedSet, network, availableNodes,
                        churnNet));
numberofRemainingNodes=availableNodes.size();
}

But I can not do that because there is not any get(index) method for Java hashSet. Would you please help me to handle this situation?

P.S: I used HashSet because of I want to handle the union and intersection situation and I did not want to add duplicate element to that. Please consider that this part of my program should be run millions of times so a little extra latency could be expensive for whole program.

FYI:

private int calculateMarginalGain(Customer remainingNode,
            HashSet<Customer> seedSet,
            DirectedSparseGraph<Customer, Transaction> net,
            Set<Customer> availableNodes, HashSet<Customer> churnNetwork) {
        // Marginal gain for short-term campaign
        HashSet<Customer> tmp = new HashSet<Customer>(); // seedset U
                                                            // {remainingNode}
        tmp.add(remainingNode);
        Set<Customer> tmpAvailableNodes = availableNodes;
        HashSet<Customer> NeighborOfChurn = getNeighbors(churnNetwork, net);
        // sigma function for calculating the expected number of influenced
        // customers- seedSettmp=seedset U {u}
        tmpAvailableNodes.removeAll(NeighborOfChurn);
        Set<Customer> influencedNet = getNeighbors(tmp, net);
        tmpAvailableNodes.retainAll(influencedNet);
        return tmpAvailableNodes.size();
    }

private HashSet<Customer> getNeighbors(HashSet<Customer> churnNetwork,
        DirectedSparseGraph<Customer, Transaction> net) {
    HashSet<Customer> churnNeighbors = churnNetwork;
    Collection<Customer> neighbors = new HashSet<Customer>();
    for (Customer node : churnNetwork) {
        neighbors = net.getNeighbors(node);
        for (Customer neighbor : neighbors) {
            churnNeighbors.add(neighbor);
        }
    }
    return churnNeighbors;
}
Was it helpful?

Solution

The problem in your code is that you change the structure of your HashSet during the iteration It is within the calculateMarginalGain() method, in this line:

tmpAvailableNodes.removeAll(NeighborOfChurn);

Think twice whether this is really right! If yes, then you can work easily around the problem by making you a copy of the set for the iteration first. E.g.:

Set<Customer> copy = new HashSet<Customer>;
copy.addAll(availableNodes);
for (Customer : copy) {
  ....
}

Actually tmpAvailableNodes and availableNodes are the identical set. Maybe you can improve here in general.

OTHER TIPS

You have to use an Iterator:

Iterator<Customer> custIter = availableNodes.iterator();
while(custIter.hasNext()) {
    Customer customer = custIter.next();
    // do your work here
}

Using this you won't get ConcurrentModificationException. It is not clear why you get it though. If you are tampering with the HashSet from multiple Threads consider using a concurrent data structure instead.

If you modify availableNodes in setMarginalGain you will still get the exception though.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top