javalambda循环_使⽤Java8Lambda简化嵌套循环操作
java lambda循环
对于每个经常需要在Java 8(或更⾼版本)中使⽤多维数组的⼈来说,这只是⼀个快速技巧。
在这种情况下,您可能经常会以类似于以下代码的结尾:
float[][] values = ...
for (int i = 0; i < values.length; i++) {
for (int k = 0; k < values[i].length; k++) {
float value = values[i][k];
// do something with i, k and value
}
}
如果幸运的话,可以⽤for-each循环替换循环。但是,循环内的计算通常需要索引。
在这种情况下,您可以提出⼀个简单的实⽤程序⽅法,如下所⽰:
private void loop(float[][] values, BiConsumer<Integer, Integer> consumer) {
for (int i = 0; i < values.length; i++) {
for (int k = 0; k < values[i].length; k++) {
consumer.accept(i, k);
}
}
}
现在,我们可以像这样循环遍历数组索引:
float[][] values = ...
loop(values, (i, k) -> {
float value = values[i][k];
// do something with i, k and value
});
这样,您可以使循环代码脱离主要逻辑。
当然,您应该更改所⽰的loop()⽅法,使其适合您的个⼈需求。
补充知识:JAVA8-lambda表达式-并⾏流,提升效率的利器?
写在前⾯的话
在前⾯我们已经看过了⼀些流的处理,那么Lambda除了在写法上的不同,还有其它什么作⽤呢?当然有,就是数据并⾏化处理!
它在某些场景下可以提⾼程序的性能。我们先看⼀个前⾯的例⼦,查所有的男同学
// 流⽅式
List<Person> newBoys = personList.stream().filter(p -> 1 == p.getSex()).List());
现在⽤并⾏流改写⼀下
// 流⽅式:出所有男同学
List<Person> newBoys = personList.parallelStream().filter(p -> 1 == p.getSex()).List());
细⼼的同学已经发现区别了,stream与parallelStream,是的,要⽤并⾏流parallelStream,就是这么简单!
什么是并⾏
有必要尝试解释⼀下,什么是数据并⾏化
Java⽀持多线程,可以同时开启多个任务。引⼊多线程的原因在于,线程可能会阻塞,CPU会主动切分时间⽚,只有分配到时间⽚的线程才会运⾏。⽽现代的处理器,⼏乎都是多核的,即多个CPU,如何才能更⾼效的利⽤硬件呢,多线程。
并⾏和多线程是有区别的,⽐如运送⼀堆货物,如果只有⼀辆车(单线程),肯定慢,平时如果货少,那还能应付过来,如果⽐如某宝的"双⼗⼀",那就肯定快递像垃圾⼀样如⼭,怎么办呢?我们可以增加车辆(多线程),那么肯定能加快运送速度。但是有⼀个前提,必须是多条道(多核CPU)。⽽在有些只有单个出⼝的地⽅,还必须排队(并发,线程安全)
⽽并⾏的针对同⼀个任务的。⽐如还是⼀辆车的货,10000件,全部放在A车上,要跑N个⼩时。现在取出⼀半放到B车上,理论上A,B2车同时跑,是不是会理快呢?嘿嘿嘿,这就是说的数据并⾏化,这⾥不会涉及并发。⽽这⼀切,Java8的并⾏流都在底层帮我们实现了
⼀定会更快?
纸上得来终觉浅,绝知此事要躬⾏!我们来看下,前⾯2个代码的分别执⾏时间
@Test
public void test() {
// 数据并⾏化处理
// 学⽣集合
Person kobe = new Person("kobe", 40, 1);
Person jordan = new Person("jordan", 50, 1);
Person mess = new Person("mess", 20, 2);
List<Person> personList = Arrays.asList(kobe, jordan, mess);
long beginTime = System.currentTimeMillis();
// 原来的⽅式
List<Person> oldBoys = new ArrayList<>(personList.size());
for (Person p : personList) {
// 性别男
if (p.getSex() == 1) {
oldBoys.add(p);
}
}
long endTime = System.currentTimeMillis();
log.info("原来的⽅式 take time:" + (endTime - beginTime));
beginTime = System.currentTimeMillis();
// 流⽅式:出所有男同学
List<Person> newBoys = personList.stream()
.filter(p -> 1 == p.getSex())
.List());
endTime = System.currentTimeMillis();
log.info("流⽅式 take time:" + (endTime - beginTime));
beginTime = System.currentTimeMillis();
// 流⽅式:出所有男同学
List<Person> parallelBoys = personList.parallelStream()
.filter(p -> 1 == p.getSex())
.List());
endTime = System.currentTimeMillis();
log.info("并⾏流⽅式 take time:" + (endTime - beginTime));
}
咦,是不是很奇怪,原来的for循环⽅式最快?多执⾏⼏次,发现结果也是这样的,那真是这样吗,我们把数据量扩⼤试试
还是更慢,换个⽅法试试
@Test
public void test() {
// 学⽣集合
List<Person> personList = new ArrayList<>(1000000);
for (int i = 0, j = 1000000; i < j; i++) {
int sex = i % 2;
Person p = new Person(String.valueOf(i), i, sex);
personList.add(p);
}
long beginTime2 = System.currentTimeMillis();
// 流⽅式:年龄之和
int parallelAges = personList.parallelStream().mapToInt(p -> p.getAge()).sum();
long endTime2 = System.currentTimeMillis();
log.info("并⾏流⽅式 take time:" + (endTime2 - beginTime2));
log.info("parallelAges:" + parallelAges);
long beginTime = System.currentTimeMillis();
// 原来的⽅式
int totalAge = 0;
for (Person p : personList) {
// 年龄之和
totalAge = totalAge + p.getAge();
}
long endTime = System.currentTimeMillis();
log.info("原来的⽅式 take time:" + (endTime - beginTime));
lambda编程log.info("totalAge:" + totalAge);
}
看看结果,还是更慢。。。这倒很出我意外,崩溃了,
可能跟我机器有关吧。所以还是需要地⽅验证,如果哪位同学能解答⼀下,欢迎指教
这⾥引⽤⼀下《java8函数式编程》的结论
⼀些条件
输⼊数据的⼤⼩。
理论上输⼊的数据越⼤,操作越复杂,并⾏流的效果越好。因为拆分数据处理,最后合并结果都会带来额外的开销。我们可以通过修改前⾯的例⼦,personList的⼤⼩来观察
可以看到,数据越⼤,并⾏效果越好。当然,真实项⽬中的处理远⽐上⾯复杂,⽽超过1000w的数据,我本地机器就OOM了尴尬
数据结构
我们通常是操作集合。⼀般来说,越好分割的并⾏速度越快。⽐如ArrayList,数组等⽀持随机读取的,效果较好。
HashSet,TreeSet,这类不容易公平的分解。⽽LinkedList,Stream.iterator等分解就⽐较困难的,效果是⽐较差的
装箱
处理包装类⽐基本类型花的时间多,⾁眼可见
核的数量
当然,如果核的数量越多,获得潜在并⾏提升速度的赶快。⽐如4核⼀般⽐双核快,对吧
以上这篇java lambda循环_使⽤Java 8 Lambda简化嵌套循环操作就是⼩编分享给⼤家的全部内容了,希望能给⼤家⼀个参考,也希望⼤家多多⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论