迭代器模式(Interator Pattern)

一、模式动机

迭代器模式(Iterator Pattern)是一种使用频率非常高的行为型设计模式,迭代器用于对一个聚合对象进行遍历。通过引入迭代器可以将数据的遍历功能从聚合对象中分离出来聚合对象只负责存储数据,而遍历数据由迭代器来完成,简化了聚合对象的设计,更符合“单一职责原则”的要求。Java语言提供了对迭代器模式的完美支持,通常我们不需要自己定义新的迭代器,直接使用Java提供的迭代器即可。迭代器模式又称为“游标(Cursor)模式”,它是一种对象行为型模式。
类比:

  • 电视机   存储电视频道的集合   聚合类(Aggregate Classes)
  • 电视机遥控器   操作电视频道   迭代器(Iterator)
  • 如何访问一个聚合对象中的元素但又不需要暴露它的内部结构,还能提供多种不同的遍历方式   迭代器模式

二、模式定义

  • 迭代器模式(Iterator Pattern) :提供一种方法来访问聚合对象,而不用暴露这个对象的内部表示。
  • 提供一个外部的迭代器对聚合对象进行访问和遍历,迭代器中定义了一个访问该聚合对象的接口,并且可以跟踪当前遍历的元素,了解哪些元素已经遍历,哪些没有。
  • 其别名为游标(Cursor)
  • 迭代器模式是一种对象行为型模式

三、模式结构

image


抽象迭代器类

public interface Iterator {
    public void first();              //将游标指向第一个元素
    public void next();               //将游标指向下一个元素
    public boolean hasNext();         //判断是否存在下一个元素
    public Object currentItem();      //获取游标指向的当前元素
}

具体迭代器类

public class ConcreteIterator implements Iterator {
    private ConcreteAggregate objects; //维持一个对具体聚合对象的引用,以便于访问存储在聚合对象中的数据
    private int cursor;         //定义一个游标,用于记录当前访问位置
    public ConcreteIterator(ConcreteAggregate objects) {
        this.objects=objects;
    }
    public void first() {  ......  }		
    public void next() {  ......  }
    public boolean hasNext( ) {  ......  }	
    public Object currentItem( ) {  ......  }
}

抽象聚合类

public interface Aggregate {
    Iterator createIterator( );
}

具体聚合类

public class ConcreteAggregate implements Aggregate {	
    ......	
    public Iterator createIterator( ) {
        return new ConcreteIterator(this);
    }
    ......
}

四、案例实现

案例背景

遥控操控电视频道遍历

案例结构

image

代码实现

抽象迭代器类:电视机遥控器类

public interface TVInterator {

    void setChannel(int i);
    Object currentChannel();
    void next();
    void previous();
    boolean isLast();
    boolean isFirst();

}

抽象聚合类

public interface Television {

    TVInterator createInterator();

}

具体电视机类:创维电视机类

public class SkyworthTelevision implements Television{

    private Object[] obj = {"CCTV-1","CCTV-2","CCTV-3","CCTV-4","CCTV-5","CCTV-6"};

    @Override
    public TVInterator createInterator() {
        return new SkyworthInterator(obj);
    }

}

具体电视机类:TCL

public class TCLTelevision implements Television{

    private Object[] obj = {"湖南卫视","上海卫视","山西卫视","河北卫视","上海卫视","北京卫视"};

    @Override
    public TVInterator createInterator() {
        return new SkyworthInterator(obj);
    }

}

具体电视机遥控器类:创维

public class SkyworthInterator implements TVInterator{

    private int currentIndex = 0;
    private Object obj[];

    public SkyworthInterator(Object[] obj) {
        this.obj = obj;
    }

    @Override
    public void setChannel(int i) {
        currentIndex = i;
    }

    @Override
    public Object currentChannel() {
        return obj[currentIndex];
    }

    @Override
    public void next() {
        if (currentIndex < obj.length){
            currentIndex ++;
        }
    }

    @Override
    public void previous() {
        if (currentIndex > 0){
            currentIndex --;
        }
    }

    @Override
    public boolean isLast() {
        return currentIndex == obj.length;
    }

    @Override
    public boolean isFirst() {
        return currentIndex ==0;
    }
}

具体电视机遥控器类:TCL

public class TCLInterator implements TVInterator{

    private int currentIndex = 0;
    private Object obj[];

    public TCLInterator(Object[] obj) {
        this.obj = obj;
    }

    @Override
    public void setChannel(int i) {
        currentIndex = i;
    }

    @Override
    public Object currentChannel() {
        return obj[currentIndex];
    }

    @Override
    public void next() {
        if (currentIndex < obj.length){
            currentIndex ++;
        }
    }

    @Override
    public void previous() {
        if (currentIndex > 0){
            currentIndex --;
        }
    }

    @Override
    public boolean isLast() {
        return currentIndex == obj.length;
    }

    @Override
    public boolean isFirst() {
        return currentIndex ==0;
    }
}

客户类

public class Client {

    public static void display(Television tv){
        TVInterator interator = tv.createInterator();
        System.out.println("电视机频道:");
        while (!interator.isLast()){
            System.out.println(interator.currentChannel().toString());
            interator.next();
        }
    }
    public static void reverseDisplay(Television tv){
        TVInterator interator = tv.createInterator();
        interator.setChannel(6);
        System.out.println("逆向遍历电视机频道:");
        while (!interator.isFirst()){
            interator.previous();
            System.out.println(interator.currentChannel().toString());
        }
    }

    public static void main(String a[]) {
        Television tv = (Television) XMLUtil.getBean();
        display(tv);
        System.out.println("===============");
        reverseDisplay(tv);
    }

}

案例分析

  • 如果需要增加一个新的具体聚合类,只需增加一个新的聚合子类和一个新的具体迭代器类即可,原有类库代码无须修改,符合开闭原则
  • 如果需要更换一个迭代器,只需要增加一个新的具体迭代器类作为抽象迭代器类的子类,重新实现遍历方法即可,原有迭代器代码无须修改,也符合开闭原则
  • 如果要在迭代器中增加新的方法,则需要修改抽象迭代器的源代码,这将违背开闭原则

五、模式分析

  • 聚合对象的两个职责:
    • 存储数据,聚合对象的基本职责
    • 遍历数据,既是可变化的,又是可分离的
  • 将遍历数据的行为从聚合对象中分离出来,封装在迭代器对象中
  • 由迭代器来提供遍历聚合对象内部数据的行为,简化聚合对象的设计,更符合单一职责原则

六、总结

模式优点

  • 支持以不同的方式遍历一个聚合对象,在同一个聚合对象上可以定义多种遍历方式
  • 简化了聚合类
  • 由于引入了抽象层,增加新的聚合类和迭代器类都很方便,无须修改原有代码,符合开闭原则

模式缺点

  • 在增加新的聚合类时需要对应地增加新的迭代器类,类的个数成对增加,这在一定程度上增加了系统的复杂性
  • 抽象迭代器的设计难度较大,需要充分考虑到系统将来的扩展。在自定义迭代器时,创建一个考虑全面的抽象迭代器并不是一件很容易的事情

使用情形

  • 访问一个聚合对象的内容而无须暴露它的内部表示
  • 需要为一个聚合对象提供多种遍历方式
  • 为遍历不同的聚合结构提供一个统一的接口,在该接口的实现类中为不同的聚合结构提供不同的遍历方式,而客户端可以一致性地操作该接口

本文来自博客园,作者:街酒,转载请注明原文链接:http://www.cnblogs.com/sorrymine/p/17421409.html

本文转载于网络 如有侵权请联系删除

相关文章

  • 并行编程基本工具

    Posix多进程进程通过fork()原语进行创建,使用kill()原语进行销毁,也可使用exit()原语自我撤销。执行fork()的进程是新创建进程的父进程。父进程可以通过wait()原语等待子进程的执行完成fork()执行成功后一共返回2次,一次返回给父进程,另外一次返回给子进程fork()创建出来的进程是不会共享内存,采用了COW的策略,父子进程在只读模式下共享变量,一旦父进程或者子进程修改变量时候,在自己的进程空间中复制这个变量进行修改。 #include<iostream> #include<chrono> #include<thread> #include<unistd.h> #include<sys/types.h> #include<sys/wait.h> intx=100; voidwait_all() { intpid; intstatus; for(;;) { pid=wait(&status); if(pid==-1) { if(errno==ECHILD) { break; } p

  • js 实现 bind 的这五层,你在第几层?

    最近在帮女朋友复习JS相关的基础知识,遇到不会的问题,她就会来问我。这不是很简单?三下五除二,分分钟解决。functionbind(fn,obj,...arr){ returnfn.apply(obj,arr) } 复制于是我就将这段代码发了过去这时候立马被女朋友进行了一连串的灵魂拷问。这个时候,我马老师就坐不住了,我不服气,我就去复习了一下bind,发现太久不写基础代码,还是会需要一点时间复习,这一次我得写一个有深度的bind,深得马老师的真传,给他分成了五层速记法。第一层-绑定在原型上的方法这一层非常的简单,得益于JS原型链的特性。由于functionxxx的原型链指向的是Function.prototype,因此我们在调用xxx.bind的时候,调用的是Function.prototype上的方法。Function.prototype._bind=function(){} 复制这样,我们就可以在一个构造函数上直接调用我们的bind方法啦~例如像这样。funcitonmyfun(){} myfun._bind(); 复制想要详细理解这方面的可以看这张图和这篇文章(https://g

  • 针对化学反应网络的贝叶斯验证(cs.CE)

    我们展现了一个数据驱动的验证方法来决定一个给出的化学反应网(CRN)满足一个给定属性,在模态逻辑中以公式展现。我们的方法由3个阶段组成,基于数据产生的模型合成形式证明。首先,我们考虑到可能模型的参数集是基于一个已知的化学计量学,并且基于兴趣属性对它们进行分类。第二,我们利用贝叶斯推理去更新参数的概率的布,而这些参数包含于一个基于潜在CRN数据的参数模型,在第三也是最终阶段,我们将两步的结果组合起来计算,潜在的CRN有多大可能性满足给定属性。我们将这种新方法应用于个案研究,并且把它比做贝叶斯统计模型校验。原文题目:BayesianVerificationofChemicalReactionNetworks原文:Wepresentadata-drivenverificationapproachthatdetermineswhetherornotagivenchemicalreactionnetwork(CRN)satisfiesagivenproperty,expressedasaformulainamodallogic.Ourapproachconsistsofthreephases,i

  • 五分钟带你回顾前端模块化发展史

    微信搜索【前端食堂】你的前端食堂,记得按时吃饭。本文已收录在前端食堂Githubhttps://github.com/Geekhyt/front-end-canteen,感谢Star。CSS早在2.1的版本就提出了@import来实现模块化,但是JavaScript直到ES6才出现官方的模块化方案ESModule。尽管早期JavaScript语言规范上不支持模块化,但这并没有阻止JavaScript的发展。官方没有模块化标准,那么我们就自己动手创建标准。社区里的前辈们创建并实现了规范,这些规范便是前端模块化发展之路上智慧的结晶。模块化的价值在2020年的今天来看,模块化应该具有以下价值:可维护性减少全局污染可复用性方便管理依赖关系分治思想的实践十年之前,模块化还只是使用「闭包」简单的实现一个命名空间。使用这种解决方式可以简单粗暴的处理全局变量和依赖关系等问题。关于闭包的概念可以参考我的另一篇文章。CommonJS让我们把时间追溯到2009年1月,在这个普通的冬天里,万物开始生长。中国南极科学考察站昆仑站落成,成为南极海拔最高的科学考察站。在JavaScript社区中,Mozilla的工

  • [Android] Android O 广播限制

    问题因为项目需要迁移到8.0平台,发现有一个系统应用打不开,从log发现如下描述:BroadcastQueue:Backgroundexecutionnotallowed:receivingIntent{...}复制实际上,在AndroidO,像下面的隐式广播都不再起作用:sendBroadcast(newIntent("this.is.an.implicit.broadcast"));复制通常来讲,这个广播会被所有注册这个action的receiver接收到。即便是在AndroidO版本,还有两类receiver仍然会接收这个广播:targetSdkVersion<=25的应用通过registerReceiver()注册的并有已经启动的进程的应用但是通过Manifest文件静态注册的BroadcastReceiver是不会接收这个广播的,反而会打印出一些开头提到的logW/BroadcastQueue:Backgroundexecutionnotallowed:receivingIntent{act=android.intent.action.PACKAGE

  • 生信类文章各区段SCI杂志推荐

    上次我们给大家推荐了几个网站(投稿期刊不为什么近年来越来越多的人对生物信息学感兴趣,因为它甚至不需要任何实验就可以发SCI,仅依靠生物信息的相关筛选和统计分析便可发文,而且图还很漂亮,是吧!高分咱就不说了,在生信领域没有一定的专业沉淀就别想了。一般纯生信或补充点相关实验大多是发1-5分文章。下面一张图显示出近些年生信文章的发文数量,可见近四年是迅速增长。1)1-2分的杂志这一类的文章要求的工作量不大,一般包含差异基因表达分析、蛋白互作网络分析、通路富集分析、生存分析等,没有试验验证及细胞试验,动物实验。根据统计,发文量前三的杂志是MolMedRep、OncolLett、Medicine。这三个杂志大家慎投,因为发文数量太多,有灌水嫌疑,你懂得。其他可选择一些相对容易的杂志选投,如下:杂志名称年发表数量MolMedRep125OncolLett43Medicine(Baltimore)12ExpTherMed11MolBiolRep11PatholResPract9PatholOncolRes7Tumori6WorldJSurgOncol6BioDataMin4ComputBiolChe

  • [菜鸟SpringCloud实战入门]第十章:分布式链路跟踪 Sleuth和Zipkin

    前言欢迎来到菜鸟SpringCloud实战入门系列(SpringCloudForNoob),该系列通过层层递进的实战视角,来一步步学习和理解SpringCloud。本系列适合有一定Java以及SpringBoot基础的同学阅读。每篇文章末尾都附有本文对应的Github源代码,方便同学调试。Github仓库地址:https://github.com/qqxx6661/springcloud_for_noob第一季菜鸟SpringCloud实战入门系列到此完结啦,下一季会择时发布,到时候会有SpringCloudGateway和其它组件的介绍哦。菜鸟SpringCloud实战入门系列你可以通过以下两种途径查看菜鸟SpringCloud实战入门系列:关注我的公众号:Rude3Knife点击公众号下方:技术推文——SpringCloud菜鸟SpringCloud实战入门专栏导航页(CSDN)实战版本SpringBoot:2.0.3.RELEASESpringCloud:Finchley.RELEASE-----正文开始-----分布式链路跟踪Sleuth和Zipkin分布式链路跟踪介绍对于一个

  • Linux:为什么那么多人讨厌 Systemd

    Systemd在Linux社区引起了无限争议。一些Linux用户对systemd的反对绝不屈从,还有一些Linux用户对systemd喜爱有加,还有很多人满不在乎。近日,关于systemd的话题又出现在社区中,很多人分享了自己的想法。一时兴起,笔者梳理了几个比较经典的回答。为什么不喜欢systemd?不断地听到很多人抱怨systemd有多么不好,但它还是被极大地普及了,并且我在网上所读到的很多文章都在介绍systemd的好处,比如更快的启动时间和更完善的日志记录,据说过去在fedora-13上开机速度测试,upstart是27秒,而systemd仅用了24秒。有人认为unix是做一件事,就把它做好,而systemd则是把pid1扩张到最大化。这可能是很多人讨厌systemd的重大原因。也有其他人认为,systemd的日志记录并不是很好,二进制日志被很多人所诟病,虽然systemd提供了更快的索引,但二进制日志本身就有问题,而且systemd的日志损坏也不是第一次发生了。而且systemd真正令人反感的是设计不够灵活,对很多人而言,systemd阻止了他们的选择自由,考虑到kFreeBS

  • Knockout.Js官网学习(Mapping插件)

    前言  Knockout设计成允许你使用任何JavaScript对象作为viewmodel。必须viewmodel的一些属性是observable的,你可以使用KO绑定他们到你的UI元素上,当这些observable值改变的时候,这些UI元素就会自动更新。使用mapping要引用的Js文件https://github.com/SteveSanderson/knockout.mapping/tree/master/build/output。手工mapping显示当前服务器时间和你网站上的当前用户数。你应该使用如下的viewmodel来代表你的这些信息:varviewModel={ serverTime:ko.observable(), numUsers:ko.observable() };复制然后绑定viewmodel到HTML元素上,如下:Thetimeontheserveris:<spandata-bind="text:serverTime"></span> and<spandata-bind="text:numUsers&

  • 如何云化你的 Windows 应用?

    AWSAppStream是一项新的亚马逊服务,它可实现Windows应用的云化,可将操作系统扩展至各种计算机和移动设备。今天,服务最实用的用例是将提供简单的游戏试玩和对高附加值应用程序(如CAD和医疗成像)提供长期支持。对于CAD应用程序的情况,AppStream允许工程师在工程现场通过平板电脑进行快速更新。而对于医疗成像应用程序,AWSAppStream让多个医学专家进行远程协作变得更为简便。开始实现客户端应用云化使用AWSAppStream需要首先考虑的是找出AppStream应用程序背后的业务模式和收入模式。如今,在美国东部地区部署这些应用程序的成本是83美分/小时。这可能是向游戏玩家提供一个全新游戏试玩供应商的可接受价格,但是在很多情况下这对于持续性游戏的运营是没有意义的。当然对于高端CAD即服务产品来说,这可能也是一个可以接受的成本支出,这个产品可以让工程师们在现场使用低端平板电脑进行CAD修改。客户端应用程序在一个专用AppStream应用程序上运行,而后者则在每一台本地设备上运行。本地应用程序对来自于亚马逊网络服务(AWS)的视频音频进行解码,并收集用户通过键盘鼠标触摸屏

  • 第二章:Shiro入门——深入浅出学Shiro细粒度权限开发框架

    Shiro是什么 ApacheShiro是一个强大易用的Java安全框架,提供了认证、授权、加密和会话管理等功能 Shiro能做什么 认证:验证用户来核实他们的身份 授权:对用户执行访问控制,如: 判断用户是否被分配了一个确定的安全角色 判断用户是否被允许做某事 会话管理:在任何环境下使用SessionAPI,即使没有Web或EJB容器。 加密:以更简洁易用的方式使用加密的功能,保护或隐藏数据防止被偷窥 Realms:聚集一个或多个用户安全数据的数据源,并作为一个单一的复合用户“视图”。 启用单点登录(SSO)功能。 为没有关联到登录的用户启用"RememberMe"服务Shiro的四大部分——身份验证,授权,会话管理和加密·Authentication:有时也简称为“登录”,这是证明用户是他们所说的他们是谁的行为。·Authorization:访问控制的过程,也就是绝对“谁”去访问“什么”。·SessionManagement:管理用户特定的会话,即使在非Web或EJB应用程序。·Cryptography:通过使用加密算法保持数据安全同时易于使用除了以上功能,sh

  • 高效Python编程之方法参数

    一、可变数量参数1、概述可变数量参数是指参数前带*的。如*args. 比如,你想要通过一些参数信息来打印日志。使用固定参数如下: deflog(message,values): ifnotvalues: print(message) else: values_str=','.join(str(x)forxinvalues) print('%s:%s'%(message,values_str)) log('Mynumbersare',[1,2]) log('Hithere',[]) >>> Mynumbersare:1,2 Hithere复制可以看出,当你没有values值传递的时候,你也不得不传递一个[]。最好的做法就是没有值,第二个参数就留空。那么你能够在最后一个参数前加*来达到这样的效果。那么最后一个参数,你传递多少个值都是合法的。如下所示: deflog(message,*values):#Theonlydifference ifnotvalues: print(message) e

  • windows可以安装安卓APP(含WSA部署小工具下载)

    微软正在加强Windows11与安卓的联动,毕竟这可以弥补他们在移动应用战略上的不足。WindowsSubsystemforAndroid升级到2204.40000.15.0,引入了几个主要的改进。在本次更新中,微软将底层引擎更新为Android12.1。也就是,Windows11设备可以使用Google的最新Android版本。官方中文名称:适用于Android的Windows子系统官方英文名称:WindowsSubsystemforAndroid习惯叫法:Windows11/Win11安卓子系统英文简称:WSAWSA介绍适用于Android的Windows子系统包括Linux内核和基于Android开源项目(AOSP)版本的Android操作系统。该子系统在Hyper-V虚拟机中运行,可以将AOSP环境中应用程序的运行时和API映射到Windows11操作系统的图形层、内存缓冲区、输入模式和传感器。WSA支持在Windows11操作系统上运行Android应用将拥有集成的体验。您可以将Android应用程序固定到Windows11“开始”菜单或任务栏,并通过鼠标、触摸或触控笔与其交

  • Omi新成员omi-router正式发布

    原文链接-https://github.com/AlloyTeam/omi/blob/master/tutorial omi-router omi-router是Omi框架专属的router插件,文件尺寸轻量,使用简便,功能强大。用于Omi制作Web单页应用的首选解决方案。 单页的好处也是非常明显: 无刷新加载页面内容 无刷新前进和后退页面 路由中的某个链接的传播和分享(别人看到的和你一样的状态) 转场动画(a标签跳转不仅要白屏,而且没有转场动画) 资源复用(单页中的许多资源一定是可以共用的,最典型的比如omi.js,如果不是单页的话,你需要加载多次) 好了,好处这么多,看看怎么安装使用吧~~ 安装 CDN 可以直接通过Unpkg.com下载或引用cdn:https://unpkg.com/omi-router/dist/omi-router.js <scriptsrc="https://unpkg.com/omi/dist/omi.js"></script> <scriptsrc="https://unpkg.com/omi-router/dist/

  • eolinker取数组数据合并成一个数据的方法

    有时候遇到数据存在某一个数组中,类似下图结构,而用到这些数据的接口又需要一个数据集合,比如这样[14224,14223]。    思路使用后置脚本,创建一个集合,把这两项数据取出来来,然后放到集合里,脚本如下 eo.http.responseParam=JSON.parse(eo.http.responseParam); letdeleteID=[]; for(vari=0;i<eo.http.responseParam.Data.OrderStores[0].GroupInfo[0].List.length;i++){ varitem=eo.http.responseParam.Data.OrderStores[0].GroupInfo[0].List[i]; deleteID.push(item.Id); } eo.env.envParam["deleteID"]=JSON.stringify(deleteID);复制 注意数据结构,特别是“[0]",不能省 创建一个空集deleteID 判断List长度,通过长度值执行循环数 每一次循环取一次Lis

  • 数数游戏

    这个游戏大家都玩过,N个人编号依次为1、2、3.。。围成一圈,从1开始数,依次2、3,但不能数k,k的倍数,和包含k的数字。现在我们稍微给一下,还是从1开始数,数到k,k的倍数,和包含k的数字的人退出。求出这N个人的退出顺序。 比如5个人,k为3,则推出顺序为31524 数据输入:一行包含两个整数分别表示N和k 数据输出:一行包含N个用空格隔开的正整数,表示N个人退出的顺序。 输入样例 53   输出样例 31524

  • 【转】Java 正则表达式详解

      正则表达式30分钟入门教程 常用正则表达式         如果你曾经用过Perl或任何其他内建正则表达式支持的语言,你一定知道用正则表达式处理文本和匹配模式是多么简单。   如果你不熟悉这个术语,那么“正则表达式”(RegularExpression)就是一个字符构成的串,它定义了一个用来搜索匹配字符串的模式。    许多语言,包括Perl、PHP、Python、JavaScript和JScript,都支持用正则表达式处理文本,一些文本编辑器用正则表达式实现高级“搜索-替换”功能。那么Java又怎样呢?本文写作时,一个包含了用正则表达式进行文本处理的Java规范需求(SpecificationRequest)已经得到认可,你可以期待在JDK的下一版本中看到它。   然而,如果现在就需要使用正则表达式,又该怎么办呢?你可以从Apache.org下载源代码开放的Jakarta-ORO库。本文接下来的内容先简要地介绍正则表达式的入门知识,然后以Jakarta-OROAPI为例介绍如何使用正则表达式。   一、正则表达式基础知

  • iOS 圆角效果

    方式1.(如果圆角视图比较少并且不复杂可以考虑使用) //通过view的layer图层进行剪切 self.nameLabel.layer.cornerRadius=5; self.nameLabel.layer.masksToBounds=YES;复制   方式2.(性能可能高点,通过画圆的方式获取image,然后再赋给视图) /** 通过上下文实现画圆形图片方式 */ -(UIImage*)circleImage { //NO代表透明 UIGraphicsBeginImageContextWithOptions(self.size,NO,0.0); //获得上下文 CGContextRefctx=UIGraphicsGetCurrentContext(); //添加一个圆,此处是关键 CGRectrect=CGRectMake(0,0,self.size.width,self.size.height); CGContextAddEllipseInRect(ctx,rect); //裁剪 CGContextClip(ctx); //将图片画上去 [selfdr

  • iOS开发tips总结

    tip1: 给UIImage添加毛玻璃效果 funcblurImage(value:NSNumber)->UIImage{    letcontext=CIContext(options:[KCIContextUseSoftwareRenderer:true])    letciImage=CoreImage.CIImage(image:self)    letblurFilter=CIFilter(name:"CIGassianBlur")    blurFilter?.setValue(ciImage,forKey:KCIInputImageKey)    blurFilter?.setValue(value,forKey:"inputRadius")    letimageRef=context.createCGImage((blurFilter?.outputImage)!,from

  • ARC141[题解]

    \(C\) 注意到一个性质: 若\(P_{2\timesi-1}>P_{2\timesi}\),那么一定有\(S_{P_{2\timesi-1}}=(\)且\(S_{P_{2\timesi}}=)\)。 若\(Q_{2\timesi-1}<Q_{2\timesi}\),那么一定有\(S_{Q_{2\timesi-1}}=(\)且\(S_{Q_{2\timesi}}=)\)。 证明: 首先有一个显然的事实,如果\(P_{2\timesi-1}>P_{2\timesi}\),那么\(P_{2\timesi-1}\)和\(P_{2\timesi}\)一定不能相同,否则交换两者位置,我们可以得到更优的序列。 对于\(Q\)同理。 接下来的问题在于,既然两者取不同即可,为什么规定\(P_{2\timesi-1}\)一定要是\((\)。 首先,对于一个合法的\(S\)串,肯定是由合法的括号序列以及合法括号序列的反转组成的。证明可以考虑一个函数\(f(x)=\sum_{i=1}^{x}A_i\),若\(S_i=(\)则\(A_i=1\)否则\(A_i=-1\)。连接函数图像得到

  • 《Effective Java》 学习笔记 —— 并发

        《EffectiveJava》第二版学习笔记之并发编程。   第66条同步访问共享的可变数据   *关键字synchronized可以保证在同一时刻只有一个线程可以执行某个方法或代码块。   *Java语音规范保证对一个变量的读操作或者写操作是原子性(atomic,注意i++是非原子性的,64位的long型或double型变量的读写操作也是非原子性的),但并不保证一个线程写入的值对另一个线程是可见的。   *避免使用Thread.stop()方法,而是采用轮询(poll)机制来终止一个线程。   *如果只需要线程间的交互通信,而不需要互斥,可以使用volatile关键字。   第67条避免过度同步   *为了避免活性失败和安全性失败,在一个被同步的方法或者代码块中,永远不要放弃对客户端的控制(避免在同步区域调用不可信代码,否则容易造成死锁、异常等问题)。   *在同步代码块内做尽可能少的事情。   第68条executor和task优先于线程   *Executorservice可以等待完成一项特殊的任务再继续执行,也可以优雅的完成终止(利用awa

相关推荐

推荐阅读