【Java】Foreach循环与迭代器

增强形for循环

List<String> list = new ArrayList<String>();
for(String s : list)
	System.out.println(s);

这么写就会遍历这个list 输出里面的全部字符串
那么他是怎么完成这个工作的呢?因为有一个Iterable的接口,这个接口包含一个能够产生Iterator的iterator()方法,并且Iterable接口被foreach用来在序列中移动,所以,只要我们创建了实现Iterable的类,都可以将它用于foreach语句中:

package iterable;

import java.util.Iterator;

public class IterableClass implements Iterable<String> {
	
	protected String[] words = ("When you have eliminated all which is impossible "
			+ "then whatever remains however improbable must be the truth").split(" ");
	
	@Override
	public Iterator<String> iterator() {
		return new Iterator<String>() {
			private int index = 0;

			@Override
			public boolean hasNext() {
				return index < words.length;
			}

			@Override
			public String next() {
				return words[index++];
			}
			
		};
	}
	
	public static void main(String[] args) {
		for(String s : new IterableClass())
			System.out.print(s + " ");
	}

}

看上面这个代码,iterator()方法返回了一个Iterator<String>的匿名内部类的实例,该匿名内部类可以遍历数组中所有的单词,基本上所以的Collection类都是Iterable类型,但是数组并不是,不存在任何从数组到Iterable的自动换换

static <E> void test(Iterable<E> ib) {
		for(E t : ib)
			System.out.println(t + " ");
	}
	
	public static void main(String[] args) {
		for(String s : new IterableClass())
			System.out.print(s + " ");
		
		test(Arrays.asList(1,2,3));
		String[] strs = {"A" , "B", "C"};
		//test(strs);
		//报错如下:
		//The method test(Iterable<E>) in the type IterableClass is not applicable for the arguments (String[])
		test(Arrays.asList(strs));
	}

那么,如果我想不光是从前向后进行遍历这个list,也许我想倒序的遍历,或者随机的遍历,怎么办呢。Android中也会在有些控件没办法满足我们特定需求的时候我们就要开始继承那个类,然后进行一些符合自己想要的操作的功能的编写
比如说:

继承自ArrayList编写了一个reversed()方法,他也返回一个Iterable类,这个类里面的iterator()方法是我们自己进行实现的,他将倒序进行输出。如果直接将对象ral放到foreach语句中,将会默认的得到前向迭代器。

package iterable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class ReversibleArrayList<E> extends ArrayList<E> {
	
	public ReversibleArrayList(Collection<E> c) {
		super(c);
	}
	
	public Iterable<E> reversed(){
		return new Iterable<E>() {

			@Override
			public Iterator<E> iterator() {
				return new Iterator<E>() {
					int current = size() - 1;

					@Override
					public boolean hasNext() {
						return current > -1;
					}

					@Override
					public E next() {
						return get(current --);
					}
				};
			}
		};
	}
}
package iterable;

import java.util.Arrays;

public class AdapterMethodIdiom {

	public static void main(String[] args) {
		ReversibleArrayList<String> ral = new ReversibleArrayList<String>(Arrays.asList("When you have eliminated all which is impossible then whatever remains however improbable must be the truth".split(" ")));
		
		for(String s : ral)
			System.out.print(s + " ");
		
		System.out.println();
		
		for(String s : ral.reversed())
			System.out.print(s + " ");
		
	}

}
//output:
When you have eliminated all which is impossible then whatever remains however improbable must be the truth 
truth the be must improbable however remains whatever then impossible is which all eliminated have you When 

下面利用这个知识,对第一次写的IterableClass类添加两种适配器方法:

package iterable;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

public class MultiIterableClass extends IterableClass {
	
	public Iterable<String> reversed(){
		return new Iterable<String>() {

			@Override
			public Iterator<String> iterator() {
				return new Iterator<String>() {
					
					int current = words.length - 1;
					
					@Override
					public boolean hasNext() {
						return current > -1;
					}

					@Override
					public String next() {
						return words[current --];
					}
				};
			}
		};
	}
	
	public Iterable<String> randomized(){
		return new Iterable<String>() {

			@Override
			public Iterator<String> iterator() {
				List<String> shuffled = new ArrayList<String>(Arrays.asList(words));
				Collections.shuffle(shuffled);
				return shuffled.iterator();
				
			}
			
		};
	}
	
	
	public static void main(String[] args) {
		MultiIterableClass mic = new MultiIterableClass();
		for(String s : mic.reversed())
			System.out.print(s + " ");
		System.out.println();
		for(String s : mic.randomized())
			System.out.print(s + " ");
		System.out.println();
		for(String s : mic)
			System.out.print(s + " ");
	}
	
}
//output:
truth the be must improbable however remains whatever then impossible is which all eliminated have you When 
eliminated then remains all be whatever truth is however improbable must the have you When impossible which 
When you have eliminated all which is impossible then whatever remains however improbable must be the truth 

看输出我们知道,第一个是倒序输出,第二个是乱序输出,但是并没有对原数组有任何影响。因为randomized方法是将Arrays.asList()方法的接口用一个ArraysList包装起来了。所以他只把list打乱了,但是不会对原数组有影响,看下面这段代码会更清晰一点:

package iterable;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;

public class ModifyingArrayAsList {

	public static void main(String[] args) {
		Random rand = new Random(47);
		Integer[] ia = {1,2,3,4,5,6,7,8,9,10};
		List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));
		System.out.println("Before shuffling: " + list1);
		
		Collections.shuffle(list1, rand);
		System.out.println("After shuffling: " + list1);
		System.out.println("array: " + Arrays.toString(ia));
		
		List<Integer> list2 = Arrays.asList(ia);
		System.out.println("Before shuffling: " + list2);
		Collections.shuffle(list2,rand);
		System.out.println("After shuffling : " + list2);
		System.out.println("Array: " + Arrays.toString(ia));
		
	}

}
//output:
Before shuffling: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
After shuffling: [4, 6, 3, 1, 8, 7, 2, 5, 10, 9]
array: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Before shuffling: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
After shuffling : [9, 1, 6, 3, 7, 2, 5, 10, 4, 8]
Array: [9, 1, 6, 3, 7, 2, 5, 10, 4, 8]

第一种情况中,Arrays.asList()的输出被传递给了ArrayList()的构造器,浙江创建爱你一个引用ia的元素的ArrayList,所以这些打乱肯定是不会修改原来的数组,但是如果直接引用的Arrays.asList(ia)的结果,这种打乱就会修改ia的顺序;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值