前一阵子在改一个项目bug,里边有这样一个功能。具体是这个样子:
功能里有一个由名字(string)组成的array[]数组,现在因为客户那里的人员调动我要把名字为“张三”的人去掉。
第一时间想到的是直接接着对数组进行操作,因为数组的长度不能改变,就另建了一个数组array2[array[].length-1]来保存出去张三后的array[]的数据。
公司的老人路过的时候问我为什么不直接用List进行操作,于是有了下面的转换代码:
User[] tempList = new User[designationLeaderList.size()]; List<User> list1= new ArrayList<User>(); for(User u: tempList){ list1.add(u); }
经过转换以后形成一个arrayList,可以直接remove掉含有张三名字的数据项,不用重现创建数组那样麻烦:
1 for(int i=0;i<list1.size();i++){ 2 if(list1.get(i).equal("张三")){ 3 list1.remove(i); 4 i--; 5 } 6 }
此处因为list在执行remove之后,第i+1个元素成为了第i个元素,所以在remove完成之后,需要执行一次i--以保证每个数据都被校验过。
另外在考虑数组和list的时候忽然想起了大学时候的数据结构,查了一下,数组之所以在java中不能改变长度是因为数组本身是保存成了一个顺序表,定义的时候数组就已经分配了固定长度且连续的储存空间,所以在java里数组长度定义以后不能变化.list采用的是链表结构,插入和删除都比较方便,长度可变.
——————————————我是分割线————————————————
公司的带我的老大看到上边的代码以后让我查一下迭代器和索引器是什么,然后在讨论这段功能的代码。
大体看了一下,java关于迭代器Iterator功能比较简单,并且只能单向移动:
(1) 使用方法iterator()要求容器返回一个Iterator。第一次调用Iterator的next()方法时,它返回序列的第一个元素。注意:iterator()方法是java.lang.Iterable接口,被Collection继承。
(2) 使用next()获得序列中的下一个元素。
(3) 使用hasNext()检查序列中是否还有元素。
(4) 使用remove()将迭代器新返回的元素删除。
Iterator是Java迭代器最简单的实现,为List设计的ListIterator具有更多的功能,它可以从两个方向遍历List,也可以从List中插入和删除元素。
具体的实现代码如下:
1 list l = new ArrayList(); 2 l.add("aa"); 3 l.add("bb"); 4 l.add("cc"); 5 for (Iterator iter = l.iterator(); iter.hasNext();) { 6 String str = (String)iter.next(); 7 System.out.println(str); 8 }
那么,用迭代器来remove张三的代码如下:
1 for(Iterator iter = list1.iterator();iter.hasNext){ 2 String name=(String)iter.next(); 3 if(name.equals("张三")){ 4 iter.remove(); 5 } 6 }
另外,java的foreach就是通过迭代器来实现的。但是在这里并不能使用foreach语句来操作。因为在foreach语句中不提供Iterator的remove()方法,但是如果用list的remove方法则会引发一个java.util.ConcurrentModificationException错误,具体原因在下面的文章中有详细解释:
http://www.cnblogs.com/dolphin0520/p/3933551.html
所以在这个功能的解决方案有两种,一种是通过普通的for循环和list的remove()来完成,另一种是通过迭代器Iterator和他的remove方法来完成。查了一下,for循环和Iterator各有不同的使用的地方:
采用ArrayList对随机访问比较快,而for循环中的get()方法,采用的即是随机访问的方法,因此在ArrayList里,for循环较快
采用LinkedList则是顺序访问比较快,iterator中的next()方法,采用的即是顺序访问的方法,因此在LinkedList里,使用iterator较快
从数据结构角度分析,for循环适合访问顺序结构,可以根据下标快速获取指定元素.而Iterator 适合访问链式结构,因为迭代器是通过next()和Pre()来定位的.可以访问没有顺序的集合.
所以在此处操作list对象的话,用Iterator的效率要更好一点。(原文参照:http://blog.csdn.net/wanghuan203/article/details/7279742)
——————————————我是分割线————————————————
而索引器并不是java里的东西,在c#中找到了相应的功能:
索引器即以类似于数组一样的用下标来访问类的数据信息的方法。有别于类似于属性用字段来访问数据信息。
具体实现代码如下:
//Student类 public Class Student { //构造函数 public Student(){} public Student(string name,int age,string hobby) { this.name = name; this.age = age; this.hobby = hobby; } //三个属性 (姓名)Name,(年龄)Age,(爱好)Hobby private string name; public String Name { get{return name;} set{name = value;} } private int age; public int Age { get{return age;} set{age = value;} } private string hobby; public string Hobby { get{return hobby;} set{hobby = value;} } //方法 public void SayHi() { Console.WriteLine("大家好,我是{0},今年{1}岁,喜欢 {2}",Name,Age.ToString(),Hobby); } } //Students类 Public Class Students { //加载时初始化stu数组 public Students() { stu[0] = new Student("rose",21,"dancing"); stu[1] = new Student("jack",22,"reading"); stu[2] = new Student("mimi",21,"singing"); } //Student类类型数组属性 private Student [] stu = new Student[3]; //整数索引器 public Student this[int index] { get{return stu[index];} } //字符串索引器 public Student this[string name] { get { int i ; bool found = false; for(i = 0;i < stu.length;i ++) { if(stu[i].Name == name) { found = true; break; } } if(found) { return stu[i]; } else {return null; } } } } Public Class Program { //Main函数中 static void Main() {Students stu = new Students(); stu[0].SayHi(); //通过索引查找 stu["rose"].SayHi(); //通过姓名查找 Console.ReadKey(); } }