热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

HashSetremoveAll方法非常慢-HashSetremoveAllmethodissurprisinglyslow

Ihaveaset–aHashSetIwanttoremovesomeitemsfromit…noneoftheitemsintheremovalsco

I have a set – a HashSet I want to remove some items from it… none of the items in the "removals" collection will be in the original set.

我有一个集合 - 一个HashSet我想从中删除一些项目......“removals”集合中的所有项目都不在原始集合中。

I specify the size of the "source" set and the size of the "removals" collection on the command line, and build both of them. The source set contains only non-negative integers; the removals set contains only negative integers. I measure how long it takes to remove all the elements using System.currentTimeMillis(), which isn’t the world most accurate stopwatch but is more than adequate in this case, as you’ll see. Here’s the code:

我在命令行中指定“source”集的大小和“removals”集合的大小,并构建它们。源集仅包含非负整数;删除集仅包含负整数。我测量使用System.currentTimeMillis()移除所有元素所需的时间,这不是世界上最精确的秒表,但在这种情况下绰绰有余,正如您将看到的那样。这是代码:

import java.util.*;
public class Test 
{ 
 public static void main(String[] args) 
 { 
    int sourceSize = Integer.parseInt(args[0]); 
    int removalsSize = Integer.parseInt(args[1]); 

    Set source = new HashSet(); 
    Collection removals = new ArrayList(); 

    for (int i = 0; i 

Let’s start off by giving it an easy job: a source set of 100 items, and 100 to remove:

让我们开始给它一个简单的工作:100个项目的源集合和100个删除:

 c:UsersJonTest>java Test 100 100
 Time taken: 1ms

Okay, That's fast as I expected.

好的,这比我想象的要快。

Next i tried source of one million items and 300,000 items to remove?

接下来我尝试了一百万件物品和300,000件物品的来源?

c:UsersJonTest>java Test 1000000 300000
Time taken: 38ms

That still seems pretty speedy. Now make it a bit easier – 300,000 source items and 300,000 removals:

这似乎仍然很快。现在让它更容易 - 300,000个源项目和300,000个删除:

c:UsersJonTest>java Test 300000 300000
Time taken: 178131ms

Nearly three minutes?

差不多三分钟?

Really confused !! can some one explain why this is happening.

真的很困惑!!有人可以解释为什么会这样。

1 个解决方案

#1


80  

The behaviour is (somewhat) documented in the javadoc:

行为(有些)记录在javadoc中:

This implementation determines which is the smaller of this set and the specified collection, by invoking the size method on each. If this set has fewer elements, then the implementation iterates over this set, checking each element returned by the iterator in turn to see if it is contained in the specified collection. If it is so contained, it is removed from this set with the iterator's remove method. If the specified collection has fewer elements, then the implementation iterates over the specified collection, removing from this set each element returned by the iterator, using this set's remove method.

此实现通过在每个集合上调用size方法来确定该集合和指定集合中较小的集合。如果此set具有较少的元素,则实现迭代该集合,依次检查迭代器返回的每个元素以查看它是否包含在指定的集合中。如果包含它,则使用迭代器的remove方法从该集合中删除它。如果指定的集合具有较少的元素,则实现将迭代指定的集合,使用此set的remove方法从此集合中删除迭代器返回的每个元素。

What this means in practice, when you call source.removeAll(removals);:

这在实践中意味着什么,当你调用source.removeAll(删除);时:

  • if the removals collection is of a smaller size than source, the remove method of HashSet is called, which is fast.

    如果删除集合的大小小于源,则调用HashSet的remove方法,这很快。

  • if the removals collection is of equal or larger size than the source, then removals.contains is called, which is slow for an ArrayList.

    如果删除集合的大小等于或大于源,则调用removals.contains,这对于ArrayList来说很慢。

Quick fix:

快速解决:

Collection removals = new HashSet();

Note that there is an open bug that is very similar to what you describe. The bottom line seems to be that it is probably a poor choice but can't be changed because it is documented in the javadoc.

请注意,有一个与您描述的非常相似的开放式错误。底线似乎是它可能是一个糟糕的选择,但不能改变,因为它记录在javadoc中。


For reference, this is the code of removeAll (in Java 8 - haven't checked other versions):

作为参考,这是removeAll的代码(在Java 8中 - 尚未检查其他版本):

public boolean removeAll(Collection c) {
    Objects.requireNonNull(c);
    boolean modified = false;

    if (size() > c.size()) {
        for (Iterator i = c.iterator(); i.hasNext(); )
            modified |= remove(i.next());
    } else {
        for (Iterator i = iterator(); i.hasNext(); ) {
            if (c.contains(i.next())) {
                i.remove();
                modified = true;
            }
        }
    }
    return modified;
}

推荐阅读
  • 如何解决《HashSetremoveAll方法非常慢》经验,为你挑选了1个好方法。 ... [详细]
  • 如何解决《JavaHashSet包含无法正常工作的函数》经验,为你挑选了1个好方法。 ... [详细]
  • 如何解决《javaHashSet中的重复项》经验,为你挑选了1个好方法。 ... [详细]
  • 如何解决《使用int数组的HashSet用法》经验,为你挑选了1个好方法。 ... [详细]
  • TheHashSetclasshasanadd(Objecto)method,whichisnotinheritedfromanotherclass.TheJavado ... [详细]
  • 这篇文章运用简单易懂的例子给大家介绍JAVAHashSet和TreeSet实现保证存入元素不会重复,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对 ... [详细]
  • 如何解决《在HashSet<T>中包含线程安全》经验,为你挑选了1个好方法。 ... [详细]
  • 如何解决《hashSet中的重复值》经验,为你挑选了1个好方法。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • Java程序设计第4周学习总结及注释应用的开发笔记
    本文由编程笔记#小编为大家整理,主要介绍了201521123087《Java程序设计》第4周学习总结相关的知识,包括注释的应用和使用类的注释与方法的注释进行注释的方法,并在Eclipse中查看。摘要内容大约为150字,提供了一定的参考价值。 ... [详细]
  • 本文介绍了一个适用于PHP应用快速接入TRX和TRC20数字资产的开发包,该开发包支持使用自有Tron区块链节点的应用场景,也支持基于Tron官方公共API服务的轻量级部署场景。提供的功能包括生成地址、验证地址、查询余额、交易转账、查询最新区块和查询交易信息等。详细信息可参考tron-php的Github地址:https://github.com/Fenguoz/tron-php。 ... [详细]
  • 本文讨论了微软的STL容器类是否线程安全。根据MSDN的回答,STL容器类包括vector、deque、list、queue、stack、priority_queue、valarray、map、hash_map、multimap、hash_multimap、set、hash_set、multiset、hash_multiset、basic_string和bitset。对于单个对象来说,多个线程同时读取是安全的。但如果一个线程正在写入一个对象,那么所有的读写操作都需要进行同步。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • Ihaveaworkfolderdirectory.我有一个工作文件夹目录。holderDir.glob(*)>holder[ProjectOne, ... [详细]
  • Java中HashSet的实现原理是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习 ... [详细]
author-avatar
妖精的尾巴的阿鲁哈
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有