• PowerCollection研究:第2枪小谈RemoveALL算法


    前一篇: 第1弹竟就发现不少问题

    盯上了BigList的RemoveAll()方法,仔细一看其算法跟List的RemoveAll实现是一致的.
    算法很简单,效率很高,但不见得新手都知道.想我以前在这里翻过跟头,拿出来分享一下吧,简单过一遍就是了.
    我们知道List在遍历的时候是不能直接删除对象的.于是乎简单明了想到的就是,先遍历一遍发现需要Remove就记录下此Item的index,将其放入一个临时的removeList里.遍历完后,"反向"遍历removeList再一个一个删除之.
    今天将这个方法跟List的RemoveAll比较测试了一下,看到结果简直想撞墙.在集合元素数目很大的情况下,有天壤之别.

    remove result  3 
    当count再大10倍,1,2分钟都没出来结果,主要是removeList太大了,容量要达到500000,系统抗议了.哇塞,中间要产生多少垃圾对象哦.
    所幸当count =1000时两者性能差不多,不过增加了垃圾回收负担,还是不划算.

    OK,看看RemoveAll算法:

    算法很简单,依次遍历一遍把那些不需要remove的item往前放.有个标识low初始值为-1,每次发现不需要Remove的Item就加1,遍历完后所有不需要Remove的Items都已被放在了low之前,因此再统一移除low后面的Items就结束此过程了.整个过程不需要removeList这样的临时容器,不额外产生垃圾对象.

    上个简明的图: (remove所有的质数)

     remove

    虽然BigList跟List的remove算法一致,但看看效率吧:

    remove result

    差别是不是很大, ==BigList返回的是所有要被移除的Item的一个集合,List只返回被移除了的个数,不公平.那么让BigList也只返回个数,再比一次结果如何:

    remove result  2

    还是有不小的差距,原因在于两者使用的底层对象不一样,一个为tree,一个为Array.List凭借着Array对内存操作的先天优势,在Remove操作上依然胜出.


    下面是反射出来的List<T>的代码:

    public int RemoveAll(Predicate<T> match)
            
    {
                
    if (match == null)
                
    {
                    ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
                }

                
    int index = 0;
                
    while ((index < this._size) && !match(this._items[index]))
                
    {
                    index
    ++;
                }

                
    if (index >= this._size)
                
    {
                    
    return 0;
                }

                
    int num2 = index + 1;
                
    while (num2 < this._size)
                
    {
                    
    while ((num2 < this._size) && match(this._items[num2]))
                    
    {
                        num2
    ++;
                    }

                    
    if (num2 < this._size)
                    
    {
                        
    this._items[index++= this._items[num2++];
                    }

                }

                Array.Clear(
    this._items, index, this._size - index);
                
    int num3 = this._size - index;
                
    this._size = index;
                
    this._version++;
                
    return num3;
            }
  • 相关阅读:
    基于Memcached的tomcat集群session共享所用的jar及多个tomcat各种序列化策略配置
    response.getWriter().write()和 response.getWriter().print()的区别
    response.getWriter().write()与out.print()的区别
    跳转到页面后加载一个请求的方法
    【遍历集合】Java遍历List,Map,Vector,Set的几种方法
    Java中通过方法创建一个http连接并请求(服务器间进行通信)
    【tomcat】手动部署动态JavaWeb项目到tomcat
    【Eclipse】Eclipse中修改项目的映射名称与端口
    使用Cookie进行会话管理
    操作系统内核框架图整理
  • 原文地址:https://www.cnblogs.com/anders06/p/792198.html
Copyright © 2020-2023  润新知