Java 8 (又称为 jdk 1.8) 是 Java 语言开发的一个主要版本。 Java 8 是oracle公司于2014年3月发布,可以看成是自Java 5 以 来最具革命性的版本。Java 8为Java语言、编译器、类库、开发 工具与JVM带来了大量新特性。
Lambda是一个匿名函数,我们可以把Lambda表达式理解为是一段可以 传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更 灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了 提升。
Lambda表达式:在Java 8 语言中引入的一种新的语法元素和操作符。这个操作符为 “->” ,该操作符被称为Lambda操作符或箭头操作符。
箭头操作符将Lambda分为两个部分:
Runnable r2 = () -> {System.out.println("我也是中国人!");};
Consumer con2 = (String s) -> {System.out.println(s);};
Consumer con2 = (s) -> {System.out.println(s);};
Consumer con2 = s -> {System.out.println(s);};
- Comparator
com2 = (o1,o2) -> { - System.out.println("xxxxxxxxx");
- return Integer.compare(o1,o2);
- };
Comparator com2 = (o1,o2) -> Integer.compare(o1,o2);
- @FunctionalInterface
- public interface A {
- String show(String s);
- }
函数式接口中使用泛型
- @FunctionalInterface
- public interface A<T> {
- public T show(T t);
- }
用Lambda表达式实例化自定义函数接口
- @Test
- public void test11(){
- //***********常规写法***************"
- A a = new A
() { - @Override
- public String show(String s) {
- return s;
- }
- }
- String zz = (String) a.show("zz");
- System.out.println(zz);
- //***********Lambda表达式写法***************"
- A a1 = s -> s;
- String yy = (String) a1.show("yy");
- System.out.println(yy);
- }
- @Test
- public void test22(){
- List
list = Arrays.asList("北京","南京","天津","东京","西京"); - //"***********常规写法***************
- filterString(list, new Predicate
() { - @Override
- public boolean test(String s) {
- return s.contains("京");
- }
- });
- //****************Lambda表达式写法***************
- List
list1 = filterString(list, s -> s.contains("京")); - System.out.println(list1);
- }
-
- //根据给定的规则,过滤集合中的字符串。此规则由Predicate的方法决定
- public List
filterString(List list, Predicate pre) { - List
filterList = new ArrayList<>(); - for (String s : list) {
- if (pre.test(s))
- filterList.add(s);
- }
- return filterList;
- }
- @Test
- public void test1(){
- Person p = new Person("张三",23);
- //***********常规写法***************"
- Supplier
sup = new Supplier() { - @Override
- public String get() {
- return p.getName();
- }
- };
- String s = sup.get();
- System.out.println(s);
- //***********Lambda表达式写法***************"
- Supplier<String> sup1 = () -> p.getName();
- System.out.println(sup1.get());
- //***********方法引用写法***************"
- Supplier
sup2 = p :: getName; - System.out.println(sup2.get());
- }
- @Test
- public void test2(){
- //***********常规写法***************"
- Comparator
com1 = new Comparator() { - @Override
- public int compare(Integer o1, Integer o2) {
- return Integer.compare(o1,o2);//Integer类的静态方法compare()
- }
- };
- System.out.println(com1.compare(11, 22));//-1
- //***********Lambda表达式写法***************"
- Comparator<Integer> com2 = (o1, o2) -> Integer.compare(o1,o2);
- System.out.println(com2.compare(22,11));//1
- //***********方法引用写法***************"
- Comparator
com3 = Integer::compare; - System.out.println(com3.compare(22, 33));//-1
- }
- @Test
- public void test3(){
- //***********常规写法***************"
- Comparator
com1 = new Comparator() { - @Override
- public int compare(String o1, String o2) {
- return o1.compareTo(o2);
- }
- };
- System.out.println(com1.compare("AA", "AB"));//-1
- //***********Lambda表达式写法***************"
- Comparator<String> com2 = (o1, o2) -> o1.compareTo(o2);
- System.out.println(com2.compare("AB", "AA"));
- //***********方法引用写法***************"
- Comparator
com3 = String :: compareTo; - System.out.println(com3.compare("AB", "AC"));//-1
- }
空参构造器引用
- @Test
- public void test1(){
- //***********常规写法***************"
- Supplier
sup1 = new Supplier() { - @Override
- public Person get() {
- return new Person();
- }
- };
- Person person = sup1.get();
- System.out.println(person);
- //***********Lambda表达式写法***************"
- Supplier<Person> sup2 = () -> new Person();
- System.out.println(sup2.get());
- //***********构造器引用写法***************"
- Supplier
sup3 = Person :: new; - System.out.println(sup3.get());
- }
带参构造器方法引用
- @Test
- public void test2(){
- //***********常规写法***************"
- BiFunction
bf1 = new BiFunction() { - @Override
- public Person apply(String s, Integer integer) {
- return new Person(s,integer);
- }
- };
- Person p1 = bf1.apply("Jack", 23);
- System.out.println(p1);
- //***********Lambda表达式写法***************"
- BiFunction<String,Integer,Person> bf2 = (s,integer) -> new Person(s,integer);
- System.out.println(bf2.apply("Tom", 24));
- //***********构造器引用写法***************"
- BiFunction
bf3 = Person :: new; - System.out.println(bf3.apply("Jerry", 25));
- }
可以把数组看做是一个特殊的类,则写法与构造器引用一致。
- @Test
- public void test3(){
- //***********常规写法***************"
- Function
fun1 = new Function() { - @Override
- public String[] apply(Integer integer) {
- return new String[integer];
- }
- };
- String[] arr1 = fun1.apply(5);
- System.out.println(Arrays.toString(arr1));
- //***********Lambda表达式写法***************"
- Function<Integer,String[]> fun2 = length -> new String[length];
- System.out.println(Arrays.toString(fun2.apply(6)));
- //***********数组引用写法***************"
- Function
fun3 = String[] ::new; - System.out.println(Arrays.toString(fun3.apply(7)));
- }
Stream关注的是对数据的运算,与CPU打交道。集合关注的是数据的存储,与内存打交道 (“集合讲的是数据,Stream讲的是计算!)
注意 :
- @Test
- public void test1(){
- List<Person> peoples = new ArrayList<>();
- peoples.add(new Person("张三",23));
- peoples.add(new Person("李四",24));
- peoples.add(new Person("王五",25));
- peoples.add(new Person("赵六",26));
-
- //default Stream<E> stream() : 返回一个顺序流
- Stream<Person> stream = peoples.stream();
- //default Stream<E> parallelStream() : 返回一个并行流
- Stream<Person> stream1 = peoples.parallelStream();
-
- }
- public void test2(){
- Person p1 = new Person("张三",23);
- Person p2 = new Person("李四",24);
-
- //调用Arrays类的static <T> Stream<T> stream(T[] array): 返回一个流
- Person[] peoples = new Person[]{p1,p2};
- Stream<Person> stream = Arrays.stream(peoples);
- }
- @Test
- public void test3(){
- Stream<String> stream = Stream.of("张三", "李四", "王五", "赵六");
- }
- @Test
- public void test4(){
- //迭代
- //public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
- Stream.iterate(0,t -> t+2).limit(10).forEach(System.out::println);
-
- //生成
- //public static<T> Stream<T> generate(Supplier<T> s)
- Stream.generate(Math::random).limit(10).forEach(System.out::println);
-
- }
多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止 操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全 部处理,称为“惰性求值”。
- List
workersList = WorkerData.getWorkers(); - Stream
stream = workersList.stream(); - //filter(Predicate p)——接收 Lambda , 从流中排除某些元素。
- stream.filter(w -> w.getSalary() > 5000).forEach(System.out::println);//查询员工表中薪资大于5000的员工信息
- List
workersList = WorkerData.getWorkers(); - //distinct()——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
- workersList.add(new Worker(1004, "雷军", 26, 7657.37));//原集合存在该条数据去重
- workersList.add(new Worker(1004, "雷军", 26, 8888));//和原数据salary不同,不会去除该条数据
- workersList.stream().distinct().forEach(System.out::println);
- List
workersList = WorkerData.getWorkers(); - // limit(n)——截断流,使其元素不超过给定数量。
- workersList.stream().limit(3).forEach(System.out::println);//获取集合中前三条数据
- List
workersList = WorkerData.getWorkers(); - //skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
- workersList.stream().skip(3).forEach(System.out::println);//获取集合中除了前三条的其余数据
- @Test
- public void test(){
- //通过集合实例化Stream
- Stream
workerStream = WorkerData.getWorkers().stream(); - //通过map()方法反射出集合中所有员工名字
- Stream
streamName = workerStream.map(Worker::getName); - //筛选出员工姓名长度大于3的员工的姓名。
- streamName.filter(name -> name.length() > 3).forEach(System.out::println);
- }
- @Test
- public void test9(){
- List
list = Arrays.asList("aa", "bb", "cc", "dd"); - //Stream里还有Stream时,通过使用map()方法需要使用二次forEach()方法进行终止操作
- //可以通过集合添加元素的add()方法和addAll()方法进行理解
- Stream
> streamStream = list.stream().map(StreamAPITest1::fromStringToStream); - streamStream.forEach(s -> s.forEach(System.out::println));
- System.out.println("****************");
- //这里我们可以使用flatMap(Function f)方法进行处理者这种情况(相当于集合添加元素的addAll()方法)
- Stream
streamStream1 = list.stream().flatMap(StreamAPITest1::fromStringToStream); - streamStream1.forEach(System.out::println);
- }
-
- //将字符串中的多个字符构成的集合转换为对应的Stream的实例
- public static Stream
fromStringToStream(String s){ - ArrayList
list = new ArrayList<>(); - for (Character c : s.toCharArray()) {
- list.add(c);
- }
- return list.stream();
- }
- @Test
- public void test5(){
- List
list = Arrays.asList(11,22,44,77,33,55); - list.stream().sorted().forEach(System.out::println);
- }
注意:自定义类要实现Comparable接口,才能使用sorted()方法
- @Test
- public void test6(){
- List
workerList = WorkerData.getWorkers(); - workerList.stream().sorted((o1,o2) ->{
- int compareAge = Integer.compare(o1.getAge(),o2.getAge());
- if (compareAge != 0)
- return compareAge;
- else {
- int compareSalary = -Double.compare(o1.getSalary(), o2.getSalary());
- return compareSalary;
- }
- }).forEach(System.out::println);
- }
以下代码演示需要用到的Worker类的对象集合:
List workerList = WorkerData.getWorkers();
- //需求:是否所有的员工的年龄都大于18
- boolean b = workerList.stream().allMatch(w -> w.getAge() > 20);
- System.out.println(b);
- //需求:是否存在员工的工资大于 10000
- boolean b1 = workerList.stream().anyMatch(w -> w.getSalary() > 10000);
- System.out.println(b1);
- //需求:是否存在员工姓“雷”
- boolean b2 = workerList.stream().noneMatch(w -> w.getName() == "张");
- System.out.println(b2);
- Optional
first = workerList.stream().findFirst(); - System.out.println(first);
- Optional
any = workerList.parallelStream().findAny(); - System.out.println(any);
- //需求:计算员工工资大于5000的员工个数
- long count = workerList.stream().filter(w -> w.getSalary() > 5000).count();
- System.out.println(count);
- //需求:查找最高的员工工资
- Optional
maxSalary = workerList.stream().map(w -> w.getSalary()).max(Double::compare); - System.out.println(maxSalary);
- //需求:查找最低的员工工资
- //写法一:
- Optional
min = workerList.stream().map(w -> w.getSalary()).min((o1,o2) -> Double.compare(o1,o2)); - System.out.println(min);//Optional[2500.32]
- //写法一:
- Optional
minSalary = workerList.stream().min((w1, w2) -> Double.compare(w1.getSalary(), w2.getSalary())); - System.out.println(minSalary);//Optional[Worker{id=1008, name='扎克伯格', age=35, salary=2500.32}]
- //使用集合的遍历操作
- workerList.forEach(System.out::println);
- System.out.println();
- //内部迭代
- workerList.stream().forEach(System.out::println);
map 和 reduce 的连接通常称为 map-reduce 模式,因 Google 用它来进行网络搜索而出名。
- //练习1:计算1-10的自然数的和
- List
list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); - Integer sum = list.stream().reduce(0, (o1, o2) -> Integer.sum(o1, o2));
- //Integer sum = list.stream().reduce(0, Integer::sum);
- System.out.println(sum);//55
- List
workerList = WorkerData.getWorkers(); - Optional
sumSalary = workerList.stream().map(w -> w.getSalary()).reduce((s1, s2) -> s1 + s2); - System.out.println(sumSalary);//Optional[48424.08]
- @Test
- public void test3(){
- List
workerList = WorkerData.getWorkers(); - //把流中元素收集到List集合中
- List
collectList = workerList.stream().filter(w -> w.getSalary() > 5000).collect(Collectors.toList()); - collectList.forEach(System.out::println);
- System.out.println();
-
- //把流中元素收集到set集合中
- Set
collectList1 = workerList.stream().filter(w -> w.getSalary() > 5000).collect(Collectors.toSet()); - collectList1.forEach(System.out::println);
- }
Collector 接口中方法的实现决定了如何对流执行收集的操作(如收集到 List、Set、 Map)。 另外,Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例, 具体方法与实例如下表:
下方代码演示用到的Student类和Teacher类
- public class Student {
- private String name;
-
- public Student() {
- }
-
- public Student(String name) {
- this.name = name;
- }
-
- public String getName() {
- return name;
- }
-
- public void setName(String name) {
- this.name = name;
- }
-
- @Override
- public String toString() {
- return "Student{" +
- "name='" + name + '\'' +
- '}';
- }
- }
- public class Teacher {
- private Student student;
-
- public Teacher() {
- }
-
- public Teacher(Student student) {
- this.student = student;
- }
-
- public Student getStudent() {
- return student;
- }
-
- public void setStudent(Student student) {
- this.student = student;
- }
-
- @Override
- public String toString() {
- return "Teacher{" +
- "student=" + student +
- '}';
- }
- }
- @Test
- public void test1(){
- Student student = new Student();
- //student = null;//java.lang.NullPointerException
- Optional
optionalStudent = Optional.of(student); - }
- @Test
- public void test2(){
- Student student = new Student();
- student = null;
- //ofNullable(T t):t可以为null
- Optional
optionalStudent = Optional.ofNullable(student); - }
Optional
- @Test
- public void test4() {
- Student student = new Student();
- //student = null;
- Optional
optionalStudent = Optional.ofNullable(student); - boolean present = optionalStudent.isPresent();
- System.out.println(present);//true(如果对象为null 返回为false)
- }
- @Test
- public void test5(){
- Student stu = new Student();
- stu.setName("张三");
- //stu = null;//如果对象为null时,ifPresent()方法返回为空
- Optional
optionalStudent = Optional.ofNullable(stu); - //方式1:
- optionalStudent.ifPresent(student -> System.out.println(student.getName()));
- //方式二:
- optionalStudent.ifPresent(new Consumer
() { - @Override
- public void accept(Student student) {
- System.out.println(student.getName());
- }
- });
- }
- @Test
- public void test6(){
- Student student = new Student();
- Optional
optionalStudent = Optional.of(student); - Student stu = optionalStudent.get();
- System.out.println(stu);
- }
- public String getStudentName(Teacher teacher){
- //return teacher.getStudent().getName();//这样写会出现空指针异常
-
- //Java1.8之前没引进Optional类的写法
- /*if (teacher != null) {
- Student student = teacher.getStudent();
- if (student != null){
- return student.getName();
- }
- }
- return null;*/
-
- //Java1.8引进Optional类的写法
- Optional
teacher1 = Optional.ofNullable(teacher); - //此时的teacher2一定非空(如果teacher1为空,则返回Jerry,如果不为空,则返回实际的对象)
- Teacher teacher2 = teacher1.orElse(new Teacher(new Student("Jerry")));
- Student student = teacher2.getStudent();
- Optional
student1 = Optional.ofNullable(student); - //此时的student2一定非空(如果student1为空,则返回Tom,如果不为空,则返回实际的对象)
- Student student2 = student1.orElse(new Student("Tom"));
- return student2.getName();
- }
- @Test
- public void test8(){
- Teacher teacher = new Teacher(new Student("Jane"));
- Optional
teacher1 = Optional.ofNullable(teacher); - Teacher teacher2 = teacher1.orElseGet(() -> new Teacher(new Student("Jerry")));
- Student student = teacher2.getStudent();
- Optional
student1 = Optional.ofNullable(student); - Student student2 = student1.orElseGet(new Supplier
() { - @Override
- public Student get() {
- return new Student("Tom");
- }
- });
- System.out.println(teacher2);//Teacher{student=Student{name='Jane'}}
- System.out.println(student2);//Student{name='Jane'}
- @Test
- public void test9() throws Throwable {
- Teacher teacher = new Teacher();
- teacher = null;
- Optional
teacher1 = Optional.ofNullable(teacher); - Teacher teacher2 = teacher1.orElseThrow(new Supplier
() { - @Override
- public Throwable get() {
- return new MyException("异常", 001);
- }
- });
- System.out.println(teacher2);
- }