在Java8中,我们经常使用lambada表达式进行foreach循环,但是常常我们在遍历List的时候想获取对象的index,但是Java8、9、10、11都没有相关的支持,同样的问题也存在于增强型for循环中,很多时候不得不含着泪以 for (int i = 0; i < list.size(); i++) 的方式写代码
我们的期望
list.foreach((item,index)->{}) //编译不通过
常见的list获取index方法
for(int i=0;i<list.size();i++>)
for (int i = 0; i < list.size(); i++) {}
indexOf(Obj)
for (Object o : list) {list.indexOf(o); //如果是Set还没有这个方法}
还有…
int i = 0;for (String s : list) {i++;}
很显然上述的方法并不是我们所想要的
Consumer和BiConsumer
我们看个简单的例子
Consumer<String> consumer = t -> System.out.println(t);consumer.accept(\"single\");BiConsumer<String, String> biConsumer = (k, v) -> System.out.println(k+\":\"+v);biConsumer.accept(\"multipart\",\"double params\");
输出结果:
singlemultipart:double params
这里不难发现我们平时写的箭头函数其实是一个Consumer或者BiConsumer对象
定制Consumer
foreach源码
default void forEach(Consumer<? super T> action) {Objects.requireNonNull(action);for (T t : this) {action.accept(t);}}
分析源码可知,我们的list foreach方法传入的是Consumer对象,支持一个参数,而我们想要的是item,index两个参数,很明显不满足,这时我们可以自定义一个Consumer,传参是BiConsumer,这样就能满足我们需求了,代码如下:
import java.util.ArrayList;import java.util.List;import java.util.function.BiConsumer;import java.util.function.Consumer;public class LambadaTools {/*** 利用BiConsumer实现foreach循环支持index** @param biConsumer* @param <T>* @return*/public static <T> Consumer<T> forEachWithIndex(BiConsumer<T, Integer> biConsumer) {/*这里说明一下,我们每次传入forEach都是一个重新实例化的Consumer对象,在lambada表达式中我们无法对int进行++操作,我们模拟AtomicInteger对象,写个getAndIncrement方法,不能直接使用AtomicInteger哦*/class IncrementInt{int i = 0;public int getAndIncrement(){return i++;}}IncrementInt incrementInt = new IncrementInt();return t -> biConsumer.accept(t, incrementInt.getAndIncrement());}}
调用示例:
List<String> list = new ArrayList();list.add(\"111\");list.add(\"222\");list.add(\"333\");list.forEach(LambadaTools.forEachWithIndex((item, index) -> {System.out.println(index +\":\"+ item);}));
输出结果如下:
0:1111:2222:333