Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.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
JDK java.util.concurrent.ConcurrentSkipListSet.equals(对象o)实现效率_Java_Performance_Collections_Iterator_Openjdk - Fatal编程技术网

JDK java.util.concurrent.ConcurrentSkipListSet.equals(对象o)实现效率

JDK java.util.concurrent.ConcurrentSkipListSet.equals(对象o)实现效率,java,performance,collections,iterator,openjdk,Java,Performance,Collections,Iterator,Openjdk,JDK中等于java.util.concurrent.ConcurrentSkipListSet的实现如下 public boolean equals(Object o) { // Override AbstractSet version to avoid calling size() if (o == this) return true; if (!(o instanceof Set)) return false; Collect

JDK中
等于
java.util.concurrent.ConcurrentSkipListSet
的实现如下

public boolean equals(Object o) {
    // Override AbstractSet version to avoid calling size()
    if (o == this)
        return true;
    if (!(o instanceof Set))
        return false;
    Collection<?> c = (Collection<?>) o;
    try {
        return containsAll(c) && c.containsAll(this);
    } catch (ClassCastException unused) {
        return false;
    } catch (NullPointerException unused) {
        return false;
    }
}
输出结果

true
2713
true
589
在JDK评论中,它说,
这个定义确保equals方法在set接口的不同实现中正常工作。
有人能解释一下吗?

作为参考,结果是创建了

JDK评论中说,
这个定义确保equals方法在set接口的不同实现中正常工作。
有人能解释一下吗

它来自中国。根据文件:

如果指定的对象也是一个集合,两个集合的大小相同,并且指定集合的每个成员都包含在此集合中(或者等效地,此集合的每个成员都包含在此指定集合中),则返回true。此定义确保equals方法在set接口的不同实现中正常工作

这意味着
Set.equals
实现应该由的行为定义。这就引出了下面的一段话:

请注意,如果排序集要正确实现set接口,则排序集维护的排序(无论是否提供显式比较器)必须与equals一致。(请参阅Comparable interface或Comparator interface以获得与equals一致的精确定义。)这是因为Set interface是根据equals操作定义的,但排序集使用其compareTo(或compare)方法执行所有元素比较,因此此方法认为相等的两个元素是,从排序集的角度来看,相等。即使排序集的顺序与equals不一致,排序集的行为也是定义良好的;它只是没有遵守Set接口的总合同

那么为什么在
ConcurrentSkipListSet
中出现“this contains that and that contains this”?首先,您希望避免呼叫,因为:

请注意,与大多数集合不同,此方法不是常数时间操作。由于这些集合的异步性质,确定当前元素的数量需要遍历它们以对它们进行计数。此外,在执行此方法的过程中,可能会更改大小,在这种情况下,返回的结果将不准确。因此,这种方法在并发应用程序中通常不是很有用

第二个原因是你想“与平等保持一致”

让我们根据您的代码制作一个残酷的示例:

private static boolean myEquals(Set o1, Set o2) {
    if (o1.size() == 1 && o2.size() == 1) {
        Iterator ic = o2.iterator();
        Iterator id = o1.iterator();

        while (ic.hasNext() && id.hasNext()) {
            if (!ic.next().equals(id.next())) {
                return false;
            }
        }
        return true;
    }
    return o1.equals(o2);
}

public static void main(String[] args) {
    print(skiplist(new BigDecimal("1.0")), tree(new BigDecimal("1.00")));
    print(skiplist(new BigDecimal("1.0")), hash(new BigDecimal("1.00")));
    print(skiplist(new BigDecimal("1.0")), identity(new BigDecimal("1.00")));
    print(skiplist(BigDecimal.ONE), identity(new BigDecimal(BigInteger.ONE, 0)));
}

private static Collection<BigDecimal> e() {
    return Arrays.asList(new BigDecimal("1.0"));
}

private static <E> Set<E> hash(E... e) {
    return new HashSet<>(Arrays.asList(e));
}

private static <E> Set<E> skiplist(E... e) {
    return new ConcurrentSkipListSet<>(Arrays.asList(e));
}

private static <E> Set<E> tree(E... e) {
    return new TreeSet<>(Arrays.asList(e));
}

private static <E> Set<E> identity(E... e) {
    Set<E> s = Collections.newSetFromMap(new IdentityHashMap<E, Boolean>());
    Collections.addAll(s, e);
    return s;
}

private static void print(Set o1, Set o2) {
    System.out.println(o1.getClass().getName()
            + "==" + o2.getClass().getName() + ": "
            + o1.equals(o2) + ": " + myEquals(o1, o2));
    System.out.println(o2.getClass().getName()
            + "==" + o1.getClass().getName() + ": " + o2.equals(o1)
            + ": " + myEquals(o2, o1));
}
该结果表明,新的实施不会:

当且仅当e1.compareTo(e2)==0对于C类的每个e1和e2具有与e1.equals(e2)相同的布尔值时,C类的自然顺序称为与equals一致。请注意,null不是任何类的实例,即使e.equals(null)返回false,e.compareTo(null)也应抛出NullPointerException

现在我们可以通过将元素检查替换为
((可比)e1)。可比((可比)e2)!=0
比较器。比较(e1,e2)!=0
并添加检查,以尝试确定两个集合使用相同的顺序,但请记住,集合可以包装,并且没有任何东西可以阻止调用方。现在您回到了equals的“this contains that and that contains this”实现,它可以处理集合包装器

“this contains that and that contains this”实现的另一个很好的属性是,equals实现没有为给定集合创建迭代器对象,而在最坏的情况下,该集合可能会有一个类似于
Arrays.asList(s.toArray()).iterator()的实现


如果不放松规范,放松现有行为,或者添加一个返回a的集合方法来捕获集合的“等价关系”,我认为很难将这样的优化添加到JDK中。

您的代码假设两个集合都是有序的。他们的没有。@EJP实际上是
ConcurrentSkipListSet
extends
NavigableSet
扩展
SortedSet
请在核心库中讨论您的问题-dev@openjdk.java.net邮件列表。谢谢@Fairoz,我稍后会发布。抱歉@EJP,我误解了,
这个
是有序的,但是
的参数等于()
即。,
对象o
可能未排序。谢谢
true
2713
true
589
private static boolean myEquals(Set o1, Set o2) {
    if (o1.size() == 1 && o2.size() == 1) {
        Iterator ic = o2.iterator();
        Iterator id = o1.iterator();

        while (ic.hasNext() && id.hasNext()) {
            if (!ic.next().equals(id.next())) {
                return false;
            }
        }
        return true;
    }
    return o1.equals(o2);
}

public static void main(String[] args) {
    print(skiplist(new BigDecimal("1.0")), tree(new BigDecimal("1.00")));
    print(skiplist(new BigDecimal("1.0")), hash(new BigDecimal("1.00")));
    print(skiplist(new BigDecimal("1.0")), identity(new BigDecimal("1.00")));
    print(skiplist(BigDecimal.ONE), identity(new BigDecimal(BigInteger.ONE, 0)));
}

private static Collection<BigDecimal> e() {
    return Arrays.asList(new BigDecimal("1.0"));
}

private static <E> Set<E> hash(E... e) {
    return new HashSet<>(Arrays.asList(e));
}

private static <E> Set<E> skiplist(E... e) {
    return new ConcurrentSkipListSet<>(Arrays.asList(e));
}

private static <E> Set<E> tree(E... e) {
    return new TreeSet<>(Arrays.asList(e));
}

private static <E> Set<E> identity(E... e) {
    Set<E> s = Collections.newSetFromMap(new IdentityHashMap<E, Boolean>());
    Collections.addAll(s, e);
    return s;
}

private static void print(Set o1, Set o2) {
    System.out.println(o1.getClass().getName()
            + "==" + o2.getClass().getName() + ": "
            + o1.equals(o2) + ": " + myEquals(o1, o2));
    System.out.println(o2.getClass().getName()
            + "==" + o1.getClass().getName() + ": " + o2.equals(o1)
            + ": " + myEquals(o2, o1));
}
java.util.concurrent.ConcurrentSkipListSet==java.util.TreeSet: true: false
java.util.TreeSet==java.util.concurrent.ConcurrentSkipListSet: true: false
java.util.concurrent.ConcurrentSkipListSet==java.util.HashSet: false: false
java.util.HashSet==java.util.concurrent.ConcurrentSkipListSet: false: false
java.util.concurrent.ConcurrentSkipListSet==java.util.Collections$SetFromMap: false: false
java.util.Collections$SetFromMap==java.util.concurrent.ConcurrentSkipListSet: false: false
java.util.concurrent.ConcurrentSkipListSet==java.util.Collections$SetFromMap: false: true
java.util.Collections$SetFromMap==java.util.concurrent.ConcurrentSkipListSet: false: true