Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ConcurrentSkipListSet删除()的问题_Java_Concurrentskiplistmap - Fatal编程技术网

Java ConcurrentSkipListSet删除()的问题

Java ConcurrentSkipListSet删除()的问题,java,concurrentskiplistmap,Java,Concurrentskiplistmap,我不确定java.util.concurrent.ConcurrentSkipListSet是否存在问题?我正在尝试向ConcurrentSkipListSet(由我自己的比较器维护的顺序)添加一些对象。添加后,我会改变一些对象的状态。我更改的属性包括比较器中使用的属性。现在,当我尝试删除一些对象时,它失败了。该对象不会从ConcurrentSkipListSet中删除,remove(object)返回false 如果我用树集替换ConcurrentSkipListSet,我看不到这种行为 我不

我不确定
java.util.concurrent.ConcurrentSkipListSet
是否存在问题?我正在尝试向ConcurrentSkipListSet(由我自己的比较器维护的顺序)添加一些对象。添加后,我会改变一些对象的状态。我更改的属性包括比较器中使用的属性。现在,当我尝试删除一些对象时,它失败了。该对象不会从ConcurrentSkipListSet中删除,
remove(object)
返回false

如果我用树集替换ConcurrentSkipListSet,我看不到这种行为

我不确定我是在做一些愚蠢的事情还是遗漏了一些东西:(。这是一个示例代码片段

public class TreeVsSkip {
static TreeSet ts = new TreeSet(new Comparator(){

    @Override
    public int compare(Object o1, Object o2) {
        if(((Emp)o1).empid == ((Emp)o2).empid){
            return 0;
        }
        if(((Emp)o1).empid > ((Emp)o2).empid){
            return 1;
        }
        return -1;
    }

});

static ConcurrentSkipListSet<Emp> csls = new ConcurrentSkipListSet(new Comparator(){

    @Override
    public int compare(Object o1, Object o2) {
        if(((Emp)o1).empid == ((Emp)o2).empid){
            return 0;
        }
        if(((Emp)o1).empid > ((Emp)o2).empid){
            return 1;
        }
        return -1;
    }

});
public static void main(String ...strings ){
    System.out.println("Testing Tree...");
    Emp e1 = new Emp(1,"abc");

    ts.add(e1);
    ts.add(new Emp(2,"pqr"));
    ts.add(new Emp(3,"xyz"));
    System.out.println(ts);
    e1.setName("test");
    e1.setId(8);
    System.out.println(ts);
    ts.remove(new Emp(3,"xyz"));
    System.out.println(ts);


    System.out.println("Testing ConcurrentSkipSet...");
    e1.setName("abc");
    e1.setId(1);
    csls.add(e1);
    csls.add(new Emp(2,"pqr"));
    csls.add(new Emp(3,"xyz"));
    System.out.println(csls);
    e1.setName("test");
    e1.setId(8);
    System.out.println(csls);
    System.out.println(csls.remove(new Emp(3,"xyz")));
    System.out.println(csls);
}

static class Emp {
    int empid;
    String name;
    Emp(int id, String n){
        empid = id;
        name = n;
    }
    void setName(String pname){
        name = pname;
    }
    void setId(int pID){
        empid = pID;
    }
    public String toString(){
        return "EmpId:"+empid+"Name:"+name;
    }
}
请注意,这种行为并不一致。有时元素会被删除

我在OSX 10.11.6版上使用java版本“1.8.0131”

为简陋的代码道歉。匆匆忙忙把它捏造出来


谢谢。

当您将项目添加到集合或用作映射中的键时,您不能更改用于比较的任何字段,例如compareTo或Comparator或hashCode/equals(视情况而定),或者您已损坏集合

删除这些项的唯一方法是迭代所有元素,并通过迭代器将其删除

顺便说一句,我会避免使用静态收集,但如果你必须,你可以这样做

static final Set<Emp> csls = new ConcurrentSkipListSet(
                                            Comparator.comparing(e -> e.empid));
static final Set csls=new ConcurrentSkipListSet(
比较(e->e.empid));

如果要更改
empid
,则需要先删除它,然后再将其添加回。为了避免意外执行此操作,我会将字段
设置为final
仅在构造函数中设置它。

是否执行
Emp
覆盖
等于
?在本例中,我没有执行此操作。但即使执行此操作,行为也会发生oesn不会改变。谢谢Peter。我同意你的看法。但是为什么对TreeSet调用remove()不会失败?除了一个是线程安全的,另一个不是线程安全的之外,这两个数据结构的语义不一样吗?更重要的是,为什么remove()会失败。我对一个对象进行了变异,删除了另一个对象,以及remove()失败。根据Javadocs,只有当contains()返回false时,它才会失败。为什么会发生这种情况?@Rajath.B您的数据结构已损坏,因此没有一个方法可以保证按预期的方式运行。特别是在树中,您可以执行O(ln)比较,所以即使改变一个不相关的节点也会阻止另一个节点上的操作,明白了吗?谢谢@Peter Lawrey
static final Set<Emp> csls = new ConcurrentSkipListSet(
                                            Comparator.comparing(e -> e.empid));