0

To make this simple, I have a method which looks up a group of keys in a hash table and insert found ones into an arraylist. The object type associated with the arraylist is the following:

public class PartitionEdge implements Comparable<PartitionEdge>
{

    public void setWeight(float weight)
    {
        this.weight = weight;
    }
    
    public float getWeight()
    {
        return this.weight;
    }
    
    public void setId(int id)
    { 
        this.id = id;
    }
    
    public int getId()
    {
        return this.id;
    }
    
    public void setFrom(PartitionVertex from)
    { 
        this.from = from;
    }
    
    public PartitionVertex getFrom()
    {
        return this.from;
    }
    
    public void setTo(PartitionVertex to)
    { 
        this.to = to;
    }
    
    public PartitionVertex getTo()
    {
        return this.to;
    }
    
    public void setLabel(int label)
    { 
        this.label = label;
    }
    
    public int getLabel()
    {
        return this.label;
    }
    
    public int PathLength = 0;
    
    protected int id;
    protected PartitionVertex from;
    protected PartitionVertex to;
    protected float weight;
    protected int label;
    

    @Override
    public int compareTo(PartitionEdge e) {
        //return Integer.compare(this.label, e.label);
        return Float.compare(this.weight, e.weight);
    }
    
}

It uses the default comparator from the Float class. But in a method where I try to call sort, one of the following exceptions will occur (originally only the one in the title).

Exception in thread "Thread-3" Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!
    at java.base/java.util.ComparableTimSort.mergeHi(ComparableTimSort.java:870)
    at java.base/java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:487)
    at java.base/java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:413)
    at java.base/java.util.ComparableTimSort.sort(ComparableTimSort.java:213)
    at java.base/java.util.Arrays.sort(Arrays.java:1107)
    at java.base/java.util.Arrays.sort(Arrays.java:1301)
    at java.base/java.util.ArrayList.sort(ArrayList.java:1721)
    at java.base/java.util.Collections.sort(Collections.java:145)
    at dedp.DistanceOracles.BridgeEdgeDOThread.run(BridgeEdgeDOThread.java:44)
java.util.ConcurrentModificationException
    at java.base/java.util.ArrayList.sort(ArrayList.java:1723)
    at java.base/java.util.Collections.sort(Collections.java:145)
    at dedp.indexes.edgedisjoint.ConnectedComponent.checkBridgeDO(ConnectedComponent.java:151)
    at dedp.Test.BridgeThreadTest.test1(BridgeThreadTest.java:109)
    at dedp.Test.BridgeThreadTest.main(BridgeThreadTest.java:122)
Exception in thread "Thread-4" Exception in thread "main" java.util.ConcurrentModificationException
    at java.base/java.util.ArrayList.sort(ArrayList.java:1723)
    at java.base/java.util.Collections.sort(Collections.java:145)
    at dedp.indexes.edgedisjoint.ConnectedComponent.checkBridgeDO(ConnectedComponent.java:152)
    at dedp.Test.BridgeThreadTest.test1(BridgeThreadTest.java:109)
    at dedp.Test.BridgeThreadTest.main(BridgeThreadTest.java:122)
java.lang.IllegalArgumentException: Comparison method violates its general contract!
    at java.base/java.util.ComparableTimSort.mergeLo(ComparableTimSort.java:748)
    at java.base/java.util.ComparableTimSort.mergeAt(ComparableTimSort.java:485)
    at java.base/java.util.ComparableTimSort.mergeCollapse(ComparableTimSort.java:413)
    at java.base/java.util.ComparableTimSort.sort(ComparableTimSort.java:213)
    at java.base/java.util.Arrays.sort(Arrays.java:1107)
    at java.base/java.util.Arrays.sort(Arrays.java:1301)
    at java.base/java.util.ArrayList.sort(ArrayList.java:1721)
    at java.base/java.util.Collections.sort(Collections.java:145)
    at dedp.DistanceOracles.BridgeEdgeDOThread.run(BridgeEdgeDOThread.java:44)

The following is my original code where the exception is raised:

public boolean checkBridgeDO(PartitionVertex source, ArrayList<PartitionEdge>bridgeList) throws ObjectNotFoundException {
        HashMap<Integer, PartitionVertex> potentialBridgeDestinations = new HashMap<>();
        boolean got=true;
        for(Map.Entry<Integer, PartitionVertex>set:bridgeVertices.entrySet()){
          float result= this.lookUp(source, set.getValue());
          if(result<0) {
              potentialBridgeDestinations.put(set.getKey(), set.getValue());
              got = false;
          }else{
              PartitionEdge e = new PartitionEdge();
              e.setFrom(source);
              e.setTo(set.getValue());
              e.setWeight(result);
              e.setLabel(this.partition.Label);
              bridgeList.add(e);
          }
        }
        if(!got){
            source.lock.lock();
            source.thread=new BridgeEdgeDOThread();
            source.underBridgeComputation=true;
       source.thread.setParameters(this,source,potentialBridgeDestinations,bridgeList,0);
            source.thread.start();
            source.lock.unlock();
        }
        Collections.sort(bridgeList);
        return got;
    }

Here the thread is trying to add more entries to the arraylist.

libinzhou
  • 37
  • 6

1 Answers1

1

The cause of the exception(in the title) is actually not related to the comparator like most other posts are talking about. It is actually because I call sort after invoking the worker thread which is also concurrently inserting entries into the same arraylist. So it is not really breaking any contracts but because of concurrency. This exception really leads me to the wrong direction for a while so I hope this can help someone in the future.

libinzhou
  • 37
  • 6