JDK8新特性详解

目录

一.lambda

1.lambda表达式

2.函数式接口

3.方法引用

4.构造器引用

5.数组引用

二.Stream API的引入

中间操作

终止操作

三、接口变化


新特性简介:

(1)速度更快

(2)代码更少

(3)Stream API

  (4)便于并行

(5)最大化减少空指针异常:Optional

  (6)Nashorn引擎,允许在JVM上运行js应用

一.lambda

1.lambda表达式

(1)利用匿名内部类创建对象,这样就不用创建接口的实现类了

//定义一个接口
public interface MyInterface {
    void  testMethod(); 	
}
package com.hbsi.jdk8;

public class Demo1 {
	public static void main(String[] args) {
		// 利用匿名内部类:创建接口的实现类
		MyInterface mif = new MyInterface() {

			@Override
			public void testMethod() {
				// TODO Auto-generated method stub
				System.out.println("利用匿名内部类:创建接口的实现类");
			}
		};
		mif.testMethod();
	}
}

(2)lambda表达式引入,利用lamnda表达式,创建接口实现类的对象,对以上代码进行改进

package com.hbsi.jdk8;

public class Demo1 {
	public static void main(String[] args) {
		// 利用lamnda表达式,创建接口实现类的对象
		MyInterface mif = () -> {
System.out.println("利用lamnda表达式,创建接口实现类的对象");

		mif.testMethod();
	}
}

(3)lambda表达式解析

   lambda表达式:本质java中接口的实现类的具体的对象
     结构

      ->叫作:箭头操作符       lambda操作符
      ->左侧:lambda的形参列表----接口中抽象方法的形参列表
      ->右侧:lambda   重写方法的方法体的具体内容

    格式:  

  •  无参  无返回值

        如 果方法体中包含多个语句,那么->右侧的{}不可以省略不写
        如果方法体中只有一个语句,那么{}可以省略不写。   

package com.hbsi.jdk8;

public class Demo1 {
	public static void main(String[] args) {
		// 利用lamnda表达式,创建接口实现类的对象
		MyInterface mif = () -> {
			int i=0;
			System.out.println("利用lamnda表达式,创建接口实现类的对象");
		};
		mif.testMethod();
	}
}

  •  有一个参数,无返回值

         lambda表达式参数 随便起名字 :num   x
         (int x) -> System.out.println("我重写了testMethod方法,方法的参数为"+x); 
         (x) -> System.out.println("我重写了testMethod方法,方法的参数为"+x);
          x-> System.out.println("我重写了testMethod方法,方法的参数为"+x); 
         只有一个参数时 ,才可以省略参数类型,省略形参列表的括号        

package com.hbsi.jdk8;

public class Demo1 {
	public static void main(String[] args) {
		// x是形参
		MyInterface mif = (x) -> {

			System.out.println("利用lamnda表达式,创建接口实现类的对象"+"x的值为"+x);
		};
		//給方法传参数  实参
		mif.testMethod(10);
	}
}
  •      两个或者两个以上的参数,执行语句多条,有返回值

            多个参数的时候,形参列表括号不可以省略不写,类型可以省略

package com.hbsi.jdk8;
//两个或者两个以上的参数,执行语句多条, 多个参数的时候,形参列表括号不可以省略不写,类型可以省略
public class Demo1 {
	public static void main(String[] args) {
		// x,y是形参
		MyInterface mif = (x,y) ->System.out.println("利用lamnda表达式,创建接口实现类的对象");
		//給方法传参数  实参
		mif.testMethod(10,20);
	}
}
  •  方法体就一句话,并且这一句话:return +返回值

       可以写成MyInterface mif = (x,y)-> "lambda"

package com.hbsi.jdk8;
public class Demo1 {
	public static void main(String[] args) {
		// x,y是形参
		MyInterface mif = (x,y) ->x+y;
		System.out.println(mif.testMethod(10,20));
		
	}
}

 总结:->左面
      *   (1)  参数类型可以省略不写----》类型推断
      *   (2)如果只有一个参数,()可以省略不写
      *       ->右面
      *   (1){}将方法体的具体内容包裹起来
      *   (2)只有一个方法体执行语句的话,{}可以省略不写
      *   (3)如果一句执行语句是return 语句,return 可以省略不写

        lambda依赖  一个接口
     * 对这个接口 有要求,要求这个接口只有一个抽象方法
     * 只有一个抽象方法的接口   ------>函数式接口

       接下来我们引入函数式接口

2.函数式接口

(1)只有一个抽象法(必须有)重写的object中方法是不会计数的  例如: Runnable Comparator
        jdk8以后可以有非抽象方法(可有可无)

package com.hbsi.jdk8;

//定义函数式接口  加@FunctionalInterface让接口中只有一个抽象方法  检测接口中的抽象方法,只能有一个
@FunctionalInterface
public interface MyInterface02 {
	void a();
 // void b(); @FunctionalInterface让接口中只有一个抽象方法 如果有此方法会报错
}

系统中的函数式接口:comparator

(3)内置函数式接口

  • 内消费型接口
    package com.hbsi.test;
    
    import java.util.function.Consumer;
    
    //1.使用的内置消费型接口
    class Demo1 {
    	public static void main(String[] args) {
    		// Consumer<Double> sm = new Consumer<Double>(){
    		//
    		// @Override
    		// public void accept(Double money) {
    		// // TODO Auto-generated method stub
    		// System.out.println("花"+money+"元买了一个吹风机");
    		// }
    		//
    		//
    	 	// };
    		Consumer<Double> sm = (Double money) -> System.out.println("花" + money + "元买了一个吹风机");
    		buySomething(2990, sm);
    	}
    
    	public static void buySomething(double money, Consumer sm) {
    		sm.accept(money);
    	}
    }

    结果:花2990.0元买了一个吹风机

  • 内置断点式接口

    package com.hbsi.test;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.function.Predicate;
    
    //断点式接口
    //案例  长度大于5字符串
    //传T返回boolean类型
    public class Demo3 {
    	public static void main(String[] args) {
         List<String> list =  Arrays.asList("afdsafsd","fasf","fasfsdsxs");
     /*    List<String> newList = filterString(list,new Predicate<String>(){
    
    		@Override
    		public boolean test(String s) {
    			// TODO Auto-generated method stub
    			return s.length()>5;
    		}
        	 
         });*/
         List<String> newList = filterString(list,( String s) ->  s.length()>5);
         for(String str:newList){
        	 System.out.println(str);
         }
    	}
    
    	// 过滤出字符串长度大于5
    	public static List<String> filterString(List<String> list, Predicate<String> p) {
    		// 定义一个新的list集合,方过滤后的字符串
    		List<String> filterList = new ArrayList<>();
            for(String s:list){
            	if(p.test(s)){
            	filterList.add(s);
            	}
            }
    		return filterList;
    
    	}
    }
    

    结果:afdsafsd
               fasfsdsxs

  • 其他的接口下来我们会在其他地方演示

3.方法引用

(1)方法引用(Method References)
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!
方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是I ambda表达式,也就是函数式接口的-一个实例。
要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致!
格式:使用操作符“.." 将类(或对象)与方法名分隔开来。

如下三种主要使用情况:
➢对象:实例方法名(非静态方法)

1.

package com.hbsi.test;

import java.io.PrintStream;
import java.util.function.Consumer;

//利用消费型接口  帮我在控制台 打印一句话
//方法引用:对象::实例方法名
public class DemoMR {
	public static void main(String[] args) {
		/*
		 * 1.PrintStream ps = System.out; Consumer cm = x->ps.println(x);
		 * cm.accept("welcome to cangzhou ");
		 */
		/**
		 * lambda表达式实现的接口中的抽象法:accept(传入参数)-----》没有返回值
		 * lambda表达式的lambda体中的具体的实现方法:println(传入参数)---》没有返回值
		 * 只要满足了:接口中的抽象方法和具体的实现方法 参数一样 返回值一样 就可以使用方法引用
		 * 实现接口中的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致!
		 */
		/*
		 * 2.PrintStream ps = System.out; 
		 * Consumer cm = ps::println;
		 * cm.accept("welcome to cangzhou ");
		 */
		//           对象::实例方法名
		Consumer cm = System.out::println;
		cm.accept("welcome to cangzhou ");
	}
}

结果:welcome to cangzhou 

以上代码从1到2到3,改写成了方法引用的方式

2.

public class Student {
	private String name;
	private int age;
	private double height;
}
package com.hbsi.test;

import java.util.function.Supplier;

//利用供给型接口,返回一个字符串
public class DemoMR1 {
	public static void main(String[] args) {
          /*  Student st = new Student("lili",18,167);
            Supplier<String> supp =() ->  st.getName();
            String str = supp.get();
            System.out.println(str );*/
		Student st = new Student("lili",18,167);
		//对象::实例方法名
        Supplier<String> supp = st::getName;
        String str = supp.get();
        System.out.println(str );
	}

结果:lili
➢类:静态方法名

package com.hbsi.test;

import java.util.Comparator;

//方法引用   类名:静态方法名
public class DemoMR2 {
	public static void main(String[] args) {
        //lambda表达式写法
		Comparator<Integer> com = (x,y)->Integer.compare(x, y);
		System.out.println(com.compare(42, 45));
		//方法引用:
		Comparator<Integer> com1 = Integer::compare;
		System.out.println(com.compare(42, 45));
	}
}

结果是:-1
              -1
➢类:实例方法名(非静态方法)


ckage com.hbsi.test;

import java.util.function.BiPredicate;

public class DemoMR3 {
	public static void main(String[] args) {
		//lambda表达式的写法   前提:方法的第一个参数  是调用方法的调用者      方法的第二个参数  是调用方法的实际传入参数
		BiPredicate<String,String> bp = (x,y)->x.equals(y);
		System.out.println(bp.test("adfas","fgsdfd"));
		//方法引用          类::实例方法名
		BiPredicate<String,String> bp2 = String::equals;
		System.out.println(bp.test("adfas","fgsdfd"));
	}
}

    结果是:false
                  false


4.构造器引用

➢默认调用的是空构造器

package com.hbsi.test01;

public class Student {
	private String name;
	private int age;
	private double height;

  其它省略
}

import java.util.function.Supplier;

//构造器的引用
//利用空构造器构造对象
public class Test {
	public static void main(String[] args) {
		// lambda表达书写法
		Supplier<Student> sup = () -> new Student();
		Student s1 = sup.get();
		System.out.println(s1);
		// 构造器引用写法
        /**
         * Student::new 这种方式的方法引用:默认调用的是空构造器
         * 原因:因为方法引用的要求 实现方法的参数   和  接口的方法参数必须一致
         * 接口中的get方法没有参数 那么构造器对应的找的也是没有参数的
         * 
         */
		Supplier<Student> sup1 = Student::new;
		Student s2 = sup.get();
		System.out.println(s2);
	}
}

结果:调用了空构造器
          Student [name=null, age=0, height=0.0]
         调用了空构造器
         Student [name=null, age=0, height=0.0]

➢调用有参构造器

package com.hbsi.test01;

import java.util.function.Function;


public class Test1 {
     public static void main(String[] args) {
		//构造器引用
    	/*调用有参构造器
    	 */
    	 Function<Integer,Student> func = Student::new;
    	 Student s2 = func.apply(18);
    	 System.out.println(s2);
	}
} 

5.数组引用

package com.hbsi.test01;

import java.util.function.Function;

//数组引用 
public class Test2 {
	public static void main(String[] args) {
       //lambda表达式写法
		Function<Integer,String[]> func = (x)-> new String[x];
		String [] str = func.apply(3);
		System.out.println(str.length);
	   //数组引用
		Function<Integer,String[]> func2 = String[]::new;
		String [] str2 = func.apply(3);
		System.out.println(str.length);
	}
}

二.Stream API的引入

[1]Stream API ( java.util. stream--java8才开始有)把真正的函数式编程风格引入到Java↑....

中。这是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
[2] Stream是Java8中处理集合的关键抽象概念 ,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用StreamAPI对集合数据 ,在java层面进行操作,就类似于使用SQL执行的数据库查询。也可以使用Stream API来并行执行操作。简言之, StreamAPI提供了一种:高效且易于使用的处理数据的方式。

[3]为什么要学习Stream API呢?

实际开发中,项目中多数数据源都来自于Mysql, Oracle等。但现在数

据源可以更多了,有MongDB, Radis等,而这些NoSQL的数据在数据库中查出来,然后就需要Java层面去处理。

[4] Stream和Collection集合的区别:

Collection是一-种静态的内存数据结构 ,而Stream是有关计算的。

中间操作

public class Student {
	private String name;
	private int age;
	private double height;

	public Student() {
		super();
		System.out.println("调用了空构造器");
		// TODO Auto-generated constructor stub
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", height=" + height + "]";
	}

	public Student(String name, int age, double height) {
		super();
		this.name = name;
		this.age = age;
		this.height = height;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public double getHeight() {
		return height;
	}

	public void setHeight(double height) {
		this.height = height;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		long temp;
		temp = Double.doubleToLongBits(height);
		result = prime * result + (int) (temp ^ (temp >>> 32));
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (age != other.age)
			return false;
		if (Double.doubleToLongBits(height) != Double.doubleToLongBits(other.height))
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

}

➢筛选与切片

package com.hbsi.test02;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Stream;

import org.junit.Test;

import com.sun.org.apache.xerces.internal.util.SynchronizedSymbolTable;

//中间操作  筛选与切片
public class Demo1 {
	List<Student> list = Arrays.asList(new Student("lili", 19, 160), new Student("lili1", 19, 166),
			new Student("lili2", 90, 180), new Student("lili3", 21, 160), new Student("lili4", 69, 161),
			new Student("lili2", 90, 180), new Student("lili2", 90, 180), new Student("lili2", 90, 180),
			new Student("lili2", 90, 180), new Student("lili5", 19, 184));

	@Test
	public void test01() {
		// 1.创建stream
		Stream<Student> stream = list.stream();
		// 2.中间操作
		// 找年龄大于18的人
		Stream<Student> stream1 = stream.filter((x) -> x.getAge() >= 18);

		// 3.终止操作
		// stream1.forEach((x)->System.out.print(x));
		stream1.forEach(System.out::println);
	}

	@Test
	public void test02() {
		// 1.创建stream
		Stream<Student> stream = list.stream();

		// 2.中间操作
		// 找年龄大于18的人
		Stream<Student> stream1 = stream.filter((x) -> {
			System.out.println("正在进行过滤");
			return x.getAge() >= 18;
		});

		// 3.终止操作 一个终止操作,执行中间操作链,产生结果 stream操作时延时的,只有执行了终止操作,才会执行中间操作
		// 我们叫“延迟加载” “惰性求值”
		// stream1.forEach((x)->System.out.print(x));
		stream1.forEach(System.out::println);
	}

	@Test
	public void test03() {
		// 感受流水线的链式操作 可以通过.添加多个操作
		list.stream().filter((x) -> {
			System.out.println("正在进行过滤");
			return x.getAge() >= 18;
		}).forEach(System.out::println);
	}

	@Test
	public void test04() {
		// 刚才利用StreamAPI进的迭代 内部迭代 -----》底层帮我做的
		// 以前写的外部迭代 -----》自己写的
		Iterator<Student> iterator = list.iterator();
		while (iterator.hasNext()) {
			Student s = iterator.next();
			if (s.getAge() >= 18) {
				System.out.println(s);
			}
		}
	}

	@Test
	public void test05() {
		// limit()短路的 只要找到满足条件 后面的就不出来了
		list.stream().filter((x) -> {
			System.out.println("正在进行过滤");
			return x.getAge() >= 18;
		}).limit(2).forEach(System.out::println);
	}

	@Test
	public void test06() {
		// skip跳过前两个满足情况的 ,显示后面满足条件的
		list.stream().filter((x) -> {
			System.out.println("正在进行过滤");
			return x.getAge() >= 18;
		}).skip(2).forEach(System.out::println);
	}

	@Test
	public void test07() {
		// distinct()方法 自定义的必须重写hashCode equals方法 因为distict实现的时候底层去找这两个方法
		list.stream().distinct().forEach(System.out::println);
	}
}

➢map映射

package com.hbsi.test02;

import java.util.Arrays;
import java.util.List;

import org.junit.Test;

public class Demo2 {
	//中间操作: map映射:接受lambda,将元素转换成其他的形式或提取信息。接受一个参数,该参数会被应用到每个元素上,并将其映射成一个新的元素
	List<Student> list = Arrays.asList(new Student("lili", 19, 160), new Student("lili1", 19, 166),
			new Student("lili2", 90, 180), new Student("lili3", 12, 160), new Student("lili4", 69, 161),
			new Student("lili2", 90, 180), new Student("lili2", 90, 180), new Student("lili2", 90, 180),
			new Student("lili2", 90, 180), new Student("lili5", 19, 184));


	@Test
	public void test01() {
		//把字符串大写输出   小写  映射成大写
		List<String> list = Arrays.asList("df", "fa", "dd");
		list.stream().map((x) -> x.toUpperCase()).forEach(System.out::println);

	}
	@Test
	public void test02() {
		//得到学生名字  相当于  把学生对象映射成名字
		list.stream().map((x) -> x.getName()).forEach(System.out::println);

	}
	@Test
	public void test03() {
		//年龄大于18的人的姓名
		list.stream().map((x)->{
			if(x.getAge()>=18){
				return x.getName();
			}
			return null;
		}).filter((x)->x!=null)
		.forEach(System.out::println);
	}
}

➢排序

package com.hbsi.test02;

import java.util.Arrays;
import java.util.List;

import org.junit.Test;

public class Demo3 {
	List<Student> list = Arrays.asList(new Student("lili", 19, 160), new Student("lili1", 19, 166),
			new Student("lili2", 90, 180), new Student("lili3", 21, 160), new Student("lili4", 69, 161),
			new Student("lili2", 90, 180), new Student("lili2", 90, 180), new Student("lili2", 90, 180),
			new Student("lili2", 90, 180), new Student("lili5", 19, 184));
	// 中间操作:排序
	@Test
	public void Test01() {
		//自然排序  底层按照内部比较器进行排序  实现了Comparable接口
		List list = Arrays.asList(1, 8, 9, 4, 3);
		list.stream().sorted().forEach(System.out::println);
	}
	@Test
	public void Test02() {
		//按照比较器进行的排序   Comparator接口   重写compare方法来指定规则
		//升序x.getAge()-y.getAge() 降序 -(x.getAge()-y.getAge())
		list.stream().sorted((x,y)->-(x.getAge()-y.getAge()))
		.forEach(System.out::println);
	}
}

➢排序

package com.hbsi.test02;

import java.util.Arrays;
import java.util.List;

import org.junit.Test;

public class Demo3 {
	List<Student> list = Arrays.asList(new Student("lili", 19, 160), new Student("lili1", 19, 166),
			new Student("lili2", 90, 180), new Student("lili3", 21, 160), new Student("lili4", 69, 161),
			new Student("lili2", 90, 180), new Student("lili2", 90, 180), new Student("lili2", 90, 180),
			new Student("lili2", 90, 180), new Student("lili5", 19, 184));
	// 中间操作:排序
	@Test
	public void Test01() {
		//自然排序  底层按照内部比较器进行排序  实现了Comparable接口
		List list = Arrays.asList(1, 8, 9, 4, 3);
		list.stream().sorted().forEach(System.out::println);
	}
	@Test
	public void Test02() {
		//按照比较器进行的排序   Comparator接口   重写compare方法来指定规则
		//升序x.getAge()-y.getAge() 降序 -(x.getAge()-y.getAge())
		list.stream().sorted((x,y)->-(x.getAge()-y.getAge()))
		.forEach(System.out::println);
	}
}

终止操作

package com.hbsi.test02;

public class Student1 {
	private String name;
	private int age;
	private double salary;
}

➢查找与匹配

package com.hbsi.test02;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

import org.junit.Test;

public class Demo4 {
	// 终止操作 查找与匹配
	List<Student> list = Arrays.asList(new Student("lili", 19, 160), new Student("lili1", 19, 166),
			new Student("lili2", 90, 180), new Student("lili3", 18, 160), new Student("lili4", 18, 161),
			new Student("lili2", 90, 180), new Student("lili2", 90, 180), new Student("lili2", 90, 180),
			new Student("lili2", 90, 180), new Student("lili5", 19, 184));

	@Test
	public void Test01() {
		// 是不是所有人的年龄都是大于18岁的 所有匹配

		boolean b = list.stream().allMatch((x) -> x.getAge() >= 18);
		System.out.println(b);
	}

	@Test
	public void Test02() {
		// 有一个人的年龄都是大于18岁的
		boolean b = list.stream().anyMatch((x) -> x.getAge() >= 18);
		System.out.println(b);
	}

	@Test
	public void Test03() {
		// (检查是否没有匹配元素) 没有匹配 返回true 有匹配false
		boolean b = list.stream().noneMatch((x) -> x.getAge() >= 18);
		System.out.println(b);
	}

	@Test
	public void Test04() {
		// 返回第一个元素 Optional专门用来解决空指针异常的 为防止为空的一个容器
		Optional<Student> findFirst = list.stream().sorted((x, y) -> x.getAge() - y.getAge()).findFirst();
		System.out.println(findFirst.get());
	}

	@Test
	public void Test05() {
		// 返回第一个元素 Optional专门用来解决空指针异常的 为防止为空的一个容器
		Optional<Student> findFirst = list.stream().sorted((x, y) -> x.getAge() - y.getAge()).findFirst();
		System.out.println(findFirst.get());
	}

	@Test
	public void Test06() {
		// 返回任何一个元素
		Optional<Student> op = list.stream().filter((x) -> x.getAge() == 18).findAny();
		System.out.println(op.get());
	}

	@Test
	public void Test07() {
		// 返回流中的元素数
		long count = list.stream().count();
		System.out.println(count);
	}

	@Test
	public void Test08() {
		// 返回流中的元素最大的
		Optional<Student> max = list.stream().max((x, y) -> x.getAge() - y.getAge());
		System.out.println(max.get());
	}

	@Test
	public void Test09() {
		// 返回流中的元素最大的
		Optional<Student> max = list.stream().min((x, y) -> x.getAge() - y.getAge());
		System.out.println(max.get());
	}

	@Test
	public void Test10() {
		// 对此流中的每个元素进行操作
		list.stream().forEach((x) -> System.out.println(x));
	}
}

➢ 归约:将流中的元素反复结合起来进行运算,得到一个值

package com.hbsi.test02;

import java.util.Arrays;
import java.util.List;

import org.junit.Test;

public class Demo5 {
	// 终止操作 归约:将流中的元素反复结合起来进行运算,得到一个值
	List<Student1> list = Arrays.asList(new Student1("lili", 19, 1600), new Student1("lili1", 19, 166),
			new Student1("lili2", 90, 1800),  
			new Student1("lili2", 90, 2800),
			new Student1("lili2", 90, 18000), new Student1("lili5", 19, 1840));
	@Test
	public void Test01(){
		List<Integer> asList = Arrays.asList(1,2,23,5);
		//reduce()方法 第二个参数继承了函数型接口 fucntion
		Integer sum = asList.stream().reduce(0,(x,y)->x+y);
		System.out.println(sum);
	}
	@Test
	public void Test02(){
		//就算每个月给员工发的工资
	Double sum1 = list.stream().map((x)->x.getSalary()).reduce(0.0,(x,y)->Double.sum(x, y));
	System.out.println(sum1);
	}

}

 ➢收集:用于给stream中元素进行汇总

package com.hbsi.test02;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import org.junit.Test;

public class Demo6 {
	//终止操作  收集:用于给stream中元素进行汇总
	
	List<Student1> list = Arrays.asList(new Student1("lili", 18, 1600), new Student1("lili1", 19, 166),
			new Student1("lili2", 90, 1800), new Student1("lili3", 90, 2800), new Student1("lili4", 90, 18000),
			new Student1("lili5", 19, 1840));
	@Test
	public void Test01(){
		//把所有学生的名字进行提取放入到指定的list集合
		List<String> list1 = list.stream().map((x)->x.getName()).collect(Collectors.toList());
		for(String str:list1){
			System.out.println(str);
			
		}
		System.out.println("--------");
	}
	@Test
	public void Test02(){
		//把所有学生的名字进行提取放入到指定的set集合
		Set<String> set = list.stream().map((x)->x.getName()).collect(Collectors.toSet());
		for(String str:set){
			System.out.println(str);
		} 
		System.out.println("--------");
	}
	@Test
	public void Test03(){
		//把所有学生的名字进行提取放入到指定的map集合
		//tomap();参数是两个函数型接口
		Map<String, Double> map = list.stream().collect(Collectors.toMap((x)->x.getName(),(y)->y.getSalary()));
		Set<Entry<String, Double>> entrySet = map.entrySet();
		for(Entry<String, Double> entry:entrySet){
			System.out.println(entry.getKey()+"  "+entry.getValue());
		}
	}
	@Test
	public void Test04(){
		//求总人数  
		Long sum = list.stream().collect(Collectors.counting());
		System.out.println(sum);
	   //工资平均值
		Double avg = list.stream().collect(Collectors.averagingDouble((x)->x.getSalary()));
		System.out.println(avg);
	  //工资总和
		Double salsum = list.stream().collect(Collectors.summingDouble((x)->x.getSalary()));
		System.out.println(salsum);
		Optional<Student1> max = list.stream().collect(Collectors.maxBy((x,y)->Double.compare(x.getSalary(),y.getSalary())));
		System.out.println(max.get());
		Optional<Student1> min = list.stream().collect(Collectors.minBy((x,y)->Double.compare(x.getSalary(),y.getSalary())));
		System.out.println(min.get());
	}
	@Test
	public void Test05(){
		//按照不同年龄进行分组
		Map<Integer, List<Student1>> map = list.stream().collect(Collectors.groupingBy((x)->x.getAge()));
                Set<Entry<Integer, List<Student1>>> entrySet = map.entrySet();
                for(Entry<Integer, List<Student1>> entry:entrySet){
        			System.out.println(entry.getKey()+"  "+entry.getValue());
        		}
	}
	@Test
	public void Test06(){
		//满足条件的在一个区,不满足条件的在一个区
		Map<Boolean, List<Student1>> map = list.stream().collect(Collectors.partitioningBy((x)->x.getAge()>=18));
                Set<Entry<Boolean, List<Student1>>> entrySet = map.entrySet();
                for(Entry<Boolean, List<Student1>> entry:entrySet){
        			System.out.println(entry.getKey()+"  "+entry.getValue());
        		}
	}
	
}

三、接口变化

java8之前接口中有常量 抽象方法

之后新增默认方法 静态方法

package com.hbsi.test03;

public interface MyInterface {
       //常量
	public static final int  NUM=20;
	  //抽象方法
	public abstract double testMethod(String str);
	 //默认方法----》跟普通方法一样
	default String eat(){
		return "我是接口中的默认方法";
	}
	public  static void play(){
		System.out.println("我是静态方法");
	}
}

( 2 )疑问: MyClass现在有个父类,父类有个方法eat(),疑问 调用eat方法的时候走父类的方法还是走接口中的默认方法?

答案:走父类中的方法,"类优先原则” 一旦父类中的方法和接口中的默认方法冲突的时候,接口中的默认方法就会忽略,就走父类的了!

(3)疑问: 一个类实现了两个接口,这两个接口中都有一个方法eat ,走谁?

当实现的接口中有冲突的默认方法的时候,那么实现类必须重新实现这个方法,然后走重新实现的方法!

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值