说在前面
上篇文章:阿里JAVA开发手册零度的思考理解(一) 得到作者孤尽的肯定支持,那是一个小激动啊,我会继续努力,继续阅读和思考阿里JAVA开发手册,毕竟每一条都是前人踩过的坑,通过血的教训总结出来的。 上篇题目回顾 看完这条,个人觉得主要是集合相关操作,在JAVA基础中集合这块的重要性也的确非常重要(毕竟是用到最多的),本期只会结合上题进行一些简单扩展,并不会涵盖所有集合操作,也不涉及集合是否线程安全这块,后期我会在我的系列高并发、锁系列里扩展深入。 集合的重要性 已经有数组了为什么会出现集合呢?依然清晰的记得数据结构里面顺序结构、链式结构的特点。在这里数组就属于顺序结构(但是集合里面根据顺序结构或者链式结构实现的都有,所以在选择用那个的时候最起码需要有那么一点点思考而不是拿什么用什么)。
备注:对于很多重复的操作,比如如果需要扩容,需要自己实现,根据编码水平不同实现的效率不一样(而且这个可能大量存在,每个人都需要实现,不符合工程学的思想),再比如需要排序,增删,遍历等等。 上面的一些问题就引入了集合并且解决了这些问题,所以集合非常重要,并且项目中集合到处可见,需要把db,nosql里面的数据接收下来。 下面看看集合具备的几个特性 :- 这种框架是高性能的,对于基本集合(动态数组、链表、树和散列表)的实现是高效的,并且是经过高度测试(不管是性能,安全等都是很可靠的)。 - 集合允许不同类型的集合以相同的方式继续操作。 - 集合是容易扩展和修改的。 集合的遍历思考 集合遍历,从工程学我们需要提供一种方法顺序访问一个集合对象中的各各元素,而又不需要暴露该对象的内部表示。 如何才能做到呢??? 迭代器模式就可以做到,下面带大家一起去了解下。 迭代器模式 迭代器模式的功能主要在于提供对聚合对象的迭代访问。主要就是这个访问进行做文章的。那么为什么使用迭代器模式呢?有什么好处呢? 集合对象的类型很多,如果对集合对象的迭代访问跟集合对象本身融合在一起的话,会严重影响到集合对象的可扩展性和可维护性。
一般情况下面,使用的都是外部迭代器(由客户端来控制迭代器的下一个元素的步骤,就是在代码里面我们需要手动调用next来迭代下一个元素,这样做就是要灵活点)JDK5之后引入的新特性foreach( 增强版for)
在稍微多做点铺垫- ArrayList对Iterator接口实现
解题 上面说了那么多,我觉得现在可以开始解题了,各位看官久等了。并发系列又是另外一个重要的话题,先不考虑并发进行分析,如果并发操作,需要对Iterator对象加锁,这个应该好理解。
所以应该注意,并不仅仅包括remove,add元素也请使用Iterator方式。 这一条标准是加了强制的,说明了重要性,按照上面的优秀实践去做就对了。 publicstaticvoidmain(String[] args) { List<String> list = new ArrayList<String>(); list.add("1"); list.add("2"); for(String item:list){ if("1".equals(item)){ //(1 换成 if("2".equals(item)){ list.remove(item); } } }123456789101112 当(1 换成 if(“2”.equals(item)){ 之后,运行结果报异常,结果如图: 其实这种给出了错误,并且有代码行数的情况其实发现查找问题都挺方便的,其实该问题的重点就变成了都是基于Iterator的输出,但是在进行删除元素的时候应该用那种方式才正确。 没有必要纠结为什么1不错,而2错,稍微看下源码就知道了,其实我们也可以让2不错,只是jdk里面就是这样实现的,它的解释和考虑如下原因。 原因
所以最佳实践就按照阿里java开发手册里面那样就好了,add元素也请使用Iterator方式。 实际工作中迭代器用法 可能说完,大家感觉迭代器就仅仅在集合遍历里面用,而且都已经有了,其实实际中的确有一些用法,反正都是围绕控制访问的,比如分页,非常常见的情况,如果每次都基于数据库分页那么怕性能不好,如果完全在内存(内存太贵,数据太多,不现实),一般的做法就是比如一页20条数据,我们一般可以每次查询数据库的时候取5页到内存(具体每次取多少可以根据用户行为分析,得到一个比较合理的,而且越到后面访问的机会越少,取到内存的就越少了,可以先比如每次都是取n页数据,在多少页之后每次取m页 之后在每次取一页一页了。n>m>1)。那么比如取出来的100条数据在内存中,需要进行根据分页访问,而原来的jdk里面的好像不满足,那么自己实现一个类似的是不是特别灵活呢?后续有空,我会在我的微信公众号,系列文章的技术思考里面把类似这块分析下的。 思考 |