想变成并发操作这样写:
// 求一个链表中的最大值
public static void main(String[] args) {
List
k = new ArrayList
(); k.add(1); k.add(2); k.add(3); k.add(8); k.add(11); k.add(20); k.add(50); Optional
max = k.parallelStream().max((a,b) -> {return a-b;}); System.out.println(max); }
很简单吧。就是将k.stream() 改成 k.parallelStream()
而这个之所以简单是基于这样几点。
1. 编写ThreadSafe的函数或者lamda表达式, 本身就很容易变为多线程操作。
2. Stream方式处理数据。
3. 传入的参数数据只关系上一步的结果,而不关系其他数据在本步所做操作产生的中间数据。
4. Fork-Join提供了很好的多线程框架
这里八卦一下Java8 为什么做了除了lamda表达式之外的一些事情。
1. interface中的default function接口。 原因是lamda表达式是为了并发做的。那么并发包concurrent中已经有了很多接口,希望和过去的版本兼容,减少迁移的工作量。如果interface中新增了接口,那么使用jdk8以前的代码就会有编译错误。要解决这个编译错误,要么抽象出一个abstract class实现接口,并加入缺省的实现。要么在以前的所有的实现中都加入这个接口。所以听听就觉得这次迁移是个大的工作量。那default function就诞生了。为了不写abstract class, 并且使用jdk5,jdk6,jdk7的代码可以方便迁移到jdk8中。default function 这样使用:
public class TestF {
public interface TestDefault {
default void print(){
System.out.println("ew2we");
}
}
public static void main(String[] args) {
// 写个匿名类
new TestDefault(){}.print();
}
}
另外值得注意的一点就是:如果有两个interface实现了同名的default function. 那编译会报错。
2. SAM (single abstract method) 也就是这个Annotation @FunctionalInterface. 如果带上这个Annotation,那么这个接口仅且只有一个未实现的方法。当然可以有多个已经实现的default 方法。这个是为了lamda表达式做的。lamda表达式是形如: (param list)-> {code statements;} ,基本上可以看作是一个函数。所以要求仅且只有一个函数方法没有实现就是为了代码好看。@FunctionalInterface 写法如下:
@FunctionalInterface
public interface DefaultInterface {
default void hello() {
System.out.println("hello");
}
default void zzz() {
System.out.println("zzz");
}
void z(); // 只有一个未实现的函数
}
3. Stream 是为了更好的使用Fork-Join框架。Stream就是pipeline. 对于只关心输入和输出的API来说。编写Stream方式的代码非常容易实现并发。其实就是把一组相似的数据丢到一个池中,然后线程池针对这些数据开始做事情。在执行完毕之前,需要join所有的线程,将最终结果放入到最终返回的池中并返回。而流式的操作最简单的就是调用方便。可以理解为以前所说的链式调用。但是对于这种编写代码的Style,还是尽量将每次调用写在不同的行中,这样会方便调试。下面是Stream的例子:
public static void main(String[] args) {
List
k = new ArrayList
(); k.add(1); k.add(2); k.add(3); k.add(8); k.add(11); k.add(20); k.add(50); // 找到list中大于2的三个数,不要求顺序,最后打印出来 k.parallelStream().filter((a)->{return a>2;}).unordered().limit(3).forEach((a) -> {System.out.println(a);}); // 获取大于1的list元素中的最大值。如果list中的元素都不大于1,那么返回Optional.empty Optional
max = k.parallelStream().filter((a)->{return a>1;}).max((a,b) -> {return a-b;}); System.out.println(max); }
这里简单介绍一下lamda表达式中语法。 这个lamda表达式就是实现了一个抽象方法。所以需要注意那个抽象方法到底是不是void返回,这关系到你的表达式中是否有return.lamda的语法是前面是参数列表,0个参数或者多于一个参数时必须使用圆括号括起。如果只有一个参数,那么可以省略圆括号。然后是一个箭头->。 再后面是函数体。函数体需要使用花括号括起,如果只有一条语句,可以省略花括号。下面的lamda表达式都是对的。
a -> return a+1;
(a) -> return a+1;
(a) -> {return a+1;}
(a,b) -> {int c = a+b; return c>>1;}
()->System.out.println("empty");
另外注意一下final 变量和this指针。
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class TestLamba {
public static class Score {
int score;
public List
findLarger(List
scores) { List
tmp = new ArrayList
(); //注意这里的this是 Score Object的this scores.stream().filter((a) -> {return a > this.score;}).forEach((a)->{tmp.add(a);}); return tmp; } public static List
findLarger(List
scores, Sc