容器遍历以及迭代器Iterator Iterable

迭代器

提供一种方法对一个容器中的各个元素进行访问,而又不暴露对象容器的内部细节。因为容器的内部结构不同,很多时候不知道该如何去遍历一个容器中的元素,为了方便操作容器内元素,提供迭代器模式。



在这之前先重温一下对于已知结构的容器的遍历方式(传统for循环)

数组使用下标

for (int i = 0; i < array.length; i++) {
   System.out.println(array[i]);
}

List使用get(角标)方法

for(int i = 0 ; i < list.size() ; i++) {
  system.out.println(list.get(i));
}

那么对于其他容器Set、Map容器内没有角标,不能使用传统for循环的或者其他不知道内部结构的容器,就需要使用迭代器或者基于迭代器实现的迭代方式。

迭代接口

Iterator接口

public interface Iterator<T>{ 
    boolean hasNext(); 
    AnyType next(); 
    void remove(); 
}

1 Java的Iterator的方法依赖当前位置,并且只能单向移动
2 使用hasNext()检查序列中是否还有下一个元素
3 使用next()方法获取序列的下一个元素
4 使用remove()方法将迭代器新进返回的元素删除

Iterable接口

public interface Iterable<T> { 
     Iterator<T> iterator(); 
} 

1 Iterable接口中包含一个iterator()方法,该方法用来返回一个Iterator类型的对象(一个实现Iterator接口的对象)
2 Iterable接口被foreach用来在序列中移动,也就是说如果创建了实现Iterable接口的类,就可以将他应用在foreach语句中
3 Collection对象全部实现了Iterable接口,与foreach一起工作是Collection对象的共性

Iterable和Iterator的关系

1 首先Iterable的实现在于通过iterator方法获取一个Iterator实例

2 Iterator对象一经创建,只能单向运动,这将意味着如果在其他的位置还要遍历一遍容器则需要再创建一个Iterator对象,这也是Iterable接口做的事情,每次调用iterator()方法便返回一个新的从头开始的Iterator迭代器,各个迭代器之间互不影响。

3 两者不是只能选择一种实现的关系,而是相辅相成的,实现Iterator接口重新next()等方法对容器内部结构遍历,实现terable接口,每次调用iterator()方法都返回一个新对象。

    如果我们需要为类A实现一个自定义的迭代器,首先要 
    a. 定义一个AIterator类实现Iterator接口,重写next()等方法
    b. 在类A中实现Iterable接口,重写iterator()方法
        public Iterator<T> iterator(){
            return new AIterator();
        }
    这两者相辅相成,这也是很多地方说,Iterator是迭代类(实现一个基础的迭代类),Iterable是迭代接口的原因

我们现在知道了两个接口,一个负责底层逻辑,一个提供操作入口,不存在任何比较关系,那现在就来看看如何使用吧

1 使用iterator方法获取一个Iterator对象并返回序列的第一个元素
2 使用hasNext()检查序列中是否还有下一个元素
3 使用next()方法获取序列的下一个元素
4 使用remove()方法将迭代器新进返回的元素删除,这个删除是作用在容器自身的,会删除掉容器内的元素

这里对这些方法有一点注意的

        Iterator iterator1 = list.iterator();
        Iterator iterator2 = list.iterator();
        //调用iterator()返回新的迭代器
  List<Integer> list = Arrays.asList(new Integer[]{1,2,3,4,5});
        Iterator iterator = list.iterator();
        while(iterator.hasNext()) {
            if(!iterator.next().equals(5)){
                System.out.println(iterator.next());
            }
        }
     //此处输出2
     //因为我们再if(!iterator.next().equals(5))以及调用了一次iteartor.next()迭代器已经前进一位
     //再输出iteartor.next()又前进一位,输出2
     //iterator.next()是动态的,并不是在一次遍历中就固定不动代表一个元素的
     //如果需要判断输出,要拿变量存储
      List<Integer> list = Arrays.asList(new Integer[]{1,2,3,4,5});
        Iterator iterator = list.iterator();
        while(iterator.hasNext()) {
            Integer i = (Integer) iterator.next();
            if(!i.equals(5)){
                System.out.println(i);
            }
        }
        //输出1
List<Integer> list = new ArrayList<Integer>(Arrays.asList(new Integer[]{1,2,3,4,5}));
        System.out.println(list);
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            Integer i = (Integer) iterator.next();
            if(i.equals(3)){
              iterator.remove();
            }
        }
        System.out.println(list);
        //输出:[1, 2, 3, 4, 5]
        //      [1, 2, 4, 5]
        //remove方法是作用的容器本身的

如何自定义一个迭代器

1 定义一个AIterator类实现Iterator接口,重写next()等方法
 private class AIterator implements Iterator<T>{
        public boolean hasNest(){
            xxxx;
        }
        public T  next() {
           xxx;
        }
        public void remove() {
           xxx;
        }
    }
2 在类A中实现Iterable接口,重写iterator()方法
public class A implements Iterable<T> {
      public Iterator<T> iterator(){
        return new AIterator();
    }
}

Collection集合中基于迭代器的遍历方法

Collection中通用的迭代器遍历 和 foreach

Iterator iterator = list.iterator();
while(iterator.hasNext()){
    int i = (Integer) iterator.next();
    System.out.println(i);
}
for (Object object : list) { 
    System.out.println(object); 
}

集合中其他遍历方法

List
1 基于角标的get方法(不是迭代器实现的),只是在这里提醒自己一下
Set

无,就是迭代器 + foreach

Map

Map是基于键值对的,所以它的迭代器实现比较特殊
就算使用迭代器通用方法也要先通过Map.entrySet拿出所有的键值对
Map类提供了一个称为entrySet()的方法,这个方法返回一个Map.Entry实例化后的对象集,可以得到Map中所有的数据信息。

1 非entrySet,一次一次get(key)
for (Integer in : map.keySet()) { //map.keySet(); //得到所有key的集合
    String str = map.get(in);//得到每个key多对用value的值
}
2 非entrySet + foreach遍历value,但是不能得到可以值
for (String v : map.values()) {//map.values(); //得到所有value的集合
    System.out.println("value= " + v);
}
3 entrySet + Iterator
Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
while (it.hasNext()) {
     Map.Entry<Integer, String> entry = it.next();
     System.out.println( entry.getKey() + entry.getValue());
}
4 entrySet + foreach(推荐 尤其是数据大时)
for (Map.Entry<Integer, String> entry : map.entrySet()) {
    System.out.println(entry.getKey() + entry.getValue());
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值