Iterable,(for each)与Iterator

本文探讨了Java中foreach循环的使用方式及其背后的Iterable接口原理,通过实例展示了如何自定义Iterable类实现遍历功能,同时介绍了适配器方法惯用法以支持反向迭代,并对比了Collections.shuffle()在不同容器上的表现差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.for each与迭代器
foreach语法主要用于数组中,同时还可以用于任何Collection对象,
其实际是foreach可以用于任何实现Iterable的类;其中Iterable接口包含产生Iterator的iterator()方法,并且Iterable接口被foreach用来在序列中移动;

import java.util.*;
public class IterableClass implements Iterable<String>
{   
    protected String[] wordsStrings=("and that is my "+"words very good").split(" ");
    @Override
    public Iterator<String> iterator() {
        // TODO Auto-generated method stub
        return new Iterator<String>() {
            private int index=0;
            @Override
            public void remove() {
                throw new UnsupportedOperationException();
                // TODO Auto-generated method stub

            }

            @Override
            public String next() {
                // TODO Auto-generated method stub
                return wordsStrings[index++];
            }

            @Override
            public boolean hasNext() {
                // TODO Auto-generated method stub
                return index<wordsStrings.length;
            }
        };
    }
public static void main(String[] args) {
    for(String s:new IterableClass())
        System.out.print(s+" ");
}
} 

Output:and that is my words very good;

注意虽然foreach可以用于数组,但不意味着数组是Iterable。
2.适配器方法惯用法
当你有一个接口并需要另一个接口时,可以编写适配器;
例如如下代码在默认的前向迭代器基础上,增加产生反向迭代器的能力,在类里添加了能够产生Iterable对象的方法;

import java.util.*;
public class ReverseList<T> extends ArrayList<T>
{   

    public ReverseList(Collection<T> c) {
        super(c);
        // TODO Auto-generated constructor stub
    }
  public Iterable<T> reversed() {
      return new Iterable<T>() {

        @Override
        public Iterator<T> iterator() {
            // TODO Auto-generated method stub
            return new Iterator<T>() {
                private int cur=size()-1;
                @Override
                public boolean hasNext() {
                    // TODO Auto-generated method stub
                    return cur>-1;
                }

                @Override
                public T next() {
                    // TODO Auto-generated method stub
                    return get(cur--);
                }

                @Override
                public void remove() {
                    // TODO Auto-generated method stub
                    throw new UnsupportedOperationException();
                }
            };
        }
    };

}
public static void main(String[] args) {
    ReverseList<String> ralList=new ReverseList<String>(Arrays.asList("to be or not to be".split(" ")));
    for (String s : ralList) {
        System.out.print(s+" ");
    }
    System.out.println();
    for (String s : ralList.reversed()) {
        System.out.print(s+" ");
    }
}
}

Output:
to be or not to be 
be to not or be to 

可以看出确实实现了前向与反向的迭代;
3.另外对于Collections.shuffle()方法对于Arrays.asList()或则对Arrays.asList()之后再次容器封装结果不同
看如下代码:

import java.util.*;
public class ReverseList
{   
  public static void main(String[] args) {
     Random random=new Random(47);
     Integer[] integers={1,2,3,4,5,6,7,8};
     List<Integer> list=new ArrayList<Integer>(Arrays.asList(integers));
     System.out.println("before shuffle:"+list);
     Collections.shuffle(list,random);
     System.out.println("after shuffle:"+list);
     System.out.println("arrays:"+Arrays.toString(integers));
     List<Integer> list2=Arrays.asList(integers);
     System.out.println("before shuffle:"+list2);
     Collections.shuffle(list2,random);
     System.out.println("after shuffle:"+list2);
     System.out.println("arrays:"+Arrays.toString(integers));
}
}

Output:
before shuffle:[1, 2, 3, 4, 5, 6, 7, 8]
after shuffle:[5, 4, 7, 1, 8, 2, 3, 6]
arrays:[1, 2, 3, 4, 5, 6, 7, 8]
before shuffle:[1, 2, 3, 4, 5, 6, 7, 8]
after shuffle:[7, 3, 1, 5, 8, 2, 6, 4]
arrays:[7, 3, 1, 5, 8, 2, 6, 4]

从中可以看出:Arrays.asList()的输出被传递给了ArrayList()的构造器,这将创建一个引用数组的元素的ArrayList,因此打乱这些引用不会修改该数组,但是,如果直接使用Arrays.asList()的结果,这种打乱会修改数组元素的顺序。所以Arrays.asList()的list对象会使用底层数组作为其物理实现,只要执行操作就会修改这个list,如果不想修改原来的数组,那么就应该在另一个容器中创建一个副本。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值