• JDK1.8新特性介绍+Lambda+函数接口+方法、构造方法和数组引用及Stream流


    JDK新特性介绍+Lambda+函数接口+方法、构造方法和数组引用及Stream流

    一、JDK新特性介绍

    • 速度更快 - 优化底层源码,比如HashMap、ConcurrentHashMap
    • 代码更少 - 添加新的语法Lambda表达式
    • 强大的Stream API
    • 便于并行
    • 最大化减少空指针异常 - Optional

    二、Lambda表达式

    1.介绍

    Lambda是一个匿名函数(方法), 允许把函数作为一个方法的参数 。利用Lambda表达式可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。一般都是优化匿名内部类

    2.基础语法

    1.无参数无返回值的抽象方法
    public class Test01 {
    
    	public static void main(String[] args) {
    		
    //		I1 i1 = new I1(){
    //
    //			@Override
    //			public void method() {
    //				System.out.println("传统的方式");
    //			}
    //		};
    //		i1.method();
    //	}
    
    //		I1 i1 = ()->{
    //		System.out.println("lamdba的方式");	
    //		};
    //		i1.method();
    		
    		I1 i1 = ()-> System.out.println("lamdba的方式");
    		i1.method();
       }
    }
    
    interface I1{
    	public void method();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    2.带参数的抽象方法
    public class Test01 {
    
    	public static void main(String[] args) {
    		
    //		I1 i1 = new I1(){
    //
    //			@Override
    //			public void method(int a, int b) {
    //				int result = a+b;
    //				System.out.println("传统方式-" + result);
    //			}
    //		};
    //		i1.method(100, 400);
    		
    //		I1 i1 = (int a,int b)->{
    //			int result = a+b;
    //			System.out.println("lamdba的方式-" + result );
    //		};
    //		i1.method(520, 520);
    		
    		//注意:lamdba中使用到外部类的变量时,该变量会变成常量
    		int i =100;
    		I1 i1 = (x,y)->{
    			int result = x+y;
    			System.out.println("lamdba的方式-" + result + "----" + i);
    		};
    		i1.method(10, 20);
    	}
    }
    
    
    interface I1 {
    	public void method(int a,int b);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    3.带返回值的抽象方法
    public class Test01 {
     
    	public static void main(String[] args) {
    //		I1 i1 = new I1(){
    //
    //			@Override
    //			public int method(int a, int b) {
    //				int result = a+b;
    //				System.out.println("传统的方式");
    //				return result;
    //			}
    //		};
    //		int num = i1.method(100, 200);
    //		System.out.println(num);
    		
    		I1 i1 = (int a,int b)->{
    			int result = a+b;
    			System.out.println("lamdba的方式");
    			return result;
    		};
    		int num = i1.method(100,150);
    		System.out.println(num);
    	}
    }
    
    interface I1{
    	public int method (int a,int b);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    4.注意点
    public class Test01 {
    
    	public static void main(String[] args) {
    		
    		//注意点1:重写方法的形参只有一个时,可以不加小括号
    //		I1 i1 = a->System.out.println(a);
    //		i1.method(100);
    		
    		//注意点2:Lambda表达式当中不允许声明一个与局部变量同名的参数或者局部变量
    		I1 i1 = (a)->System.out.println(a);
    		i1.method(200);
    	}
    }
    
    interface I1{
    	public void method(int a);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    5.Lamdba的案例
    1.调用Collections.sort()方法

    调用Collections.sort()方法,通过定制排序比较两个Student对象

    (先按年龄比较,年龄相同按照薪资比较),使用Lambda表达式作为参数传递

    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;
    
    public class Test01 {
    
    	public static void main(String[] args) {
    		
    		List<Student> stuList = Arrays.asList(
    				new Student("张飞", 31, 4800,Role.WARRIOR),
    				new Student("后裔", 28, 7200,Role.SHOOTER),
    				new Student("夏侯惇", 19, 9600,Role.WARRIOR),
    				new Student("妲己", 28, 6100,Role.MASTER),
    				new Student("孙尚香", 23, 9600,Role.SHOOTER),
    				new Student("安吉拉", 28, 3000,Role.MASTER));
    		
    //		Collections.sort(stuList,new Comparator() {
    //
    //			@Override
    //			public int compare(Student o1, Student o2) {
    //				int age1 = o1.getAge();
    //				int age2 = o2.getAge();
    //				if(age1 != age2){
    //					return Integer.compare(age1, age2);
    //				}
    //				
    //				double blood1 = o1.getBlood();
    //				double blood2 = o2.getBlood();
    //				if(blood1 != blood2){
    //					return Double.compare(blood1, blood2);
    //				}
    //				return 1;
    //			}
    //		});
    		
    		Collections.sort(stuList,(stu1,stu2)->{
    			int age1 = stu1.getAge();
    			int age2 = stu2.getAge();
    			if(age1 != age2){
    				return Integer.compare(age1, age2);
    			}
    			
    			double salary1 = stu1.getBlood();
    			double salary2 = stu2.getBlood();
    			if(salary1 != salary2){
    				return Double.compare(salary1, salary2);
    			}
    			return 1;
    		});
    		
    		
    		for (Student stu : stuList) {
    			System.out.println(stu);
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    public class Student {
    
    	private String name;
    	private int age;
    	private double blood;
    	private Role role;
    	
    	public Student() {
    	}
    
    	public Student(String name, int age, double blood, Role role) {
    		this.name = name;
    		this.age = age;
    		this.blood = blood;
    		this.role = role;
    	}
    
    	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 getBlood() {
    		return blood;
    	}
    
    	public void setBlood(double blood) {
    		this.blood = blood;
    	}
    
    	public Role getRole() {
    		return role;
    	}
    
    	public void setRole(Role role) {
    		this.role = role;
    	}
    
    	@Override
    	public String toString() {
    		return "Student [name=" + name + ", age=" + age + ", blood=" + blood + ", role=" + role + "]";
    	}
    	
    	
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    public enum Role {
    
    	MASTER,SHOOTER,WARRIOR;
    }
    
    • 1
    • 2
    • 3
    • 4
    2.创建抽象方法

    创建I1接口,创建抽象方法:public String getValue(String str),

    在测试类中编写方法使用接口作为参数,将一个字符串转为大写,并作为方法的返回值

    public class Test01 {
    
    	public static void main(String[] args) {
    		String strHandler =	strHandeler("abc",(str)->str.toUpperCase());
    		System.out.println(strHandler);
    	}
    	
    	public static String strHandeler(String str,I1 i1){
    		return i1.getValue(str);
    	}
    }
    
    interface I1{
    	public String getValue(String str);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    3.创建I1接口

    创建I1接口,泛型T为参数,R为返回值,创建抽象方法:public R add(T t1,T t2),

    在测试类中编写方法使用接口作为参数,计算两个long类型的和

    public class Test01 {
    
    	public static void main(String[] args) {
    		
    		long addLong = addLong(10,20,(a,b)->a+b);
    		System.out.println(addLong);
    	}
    	
    	public static long addLong(long a,long b,I1<Long,Long> i1){
    		return i1.add(a,b);
    	}
    }
    
    interface I1 <T,R>{
    	public R add(T t1,T t2);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    三、函数式接口

    函数式接口是指仅仅只包含一个抽象方法的接口,jdk1.8提供了一个@FunctionalInterface注解来定义函数式接口,如果我们定义的接口不符合函数式的规范便会报错。配合Lambda表达式一起使用

    函数式接口参数类型返回类型用途
    Consumer 消费型接口Tvoidvoid accept(T t);
    Supplier 供给型接口voidTT get();
    Function 函数型接口TRR apply(T t);
    Predicate 断言型接口Tbooleanbooelan test(T t);
    BiConsumerT,Uvoid对类型为T,U参数应用操作。包含方 法为void accept(T t,U u);
    BiFunctionT,UR对类型为T,U参数应用操作,并返回R类型的结果。包含方法为R apply(T t,U u);
    UnaryOperator extends FunctionT,TT对类型为T的对象进行二元运算,并返回T类型的结果。包含方法为T apply(T t1,T t2);
    BinaryOperator extends BiFunctionT,TT对类型为T的对象进行二元运算,并返回T类型的结果。包含方法为T apply(T t1,T t2);
    ToIntFunction ToLongFunction ToDoubleFunctionTint long double分别计算int、long、double值的函数
    IntFunction LongFunction DoubleFunctionint long doubleR参数为int、long、double类型的函数
    1.创建I1<T,R>接口,泛型T为参数,R为返回值,创建抽象方法:public R add(T t1,T t2), 在测试类中编写方法使用接口作为参数,计算两个long类型的和
      
        方法一、
    import java.util.function.BiFunction;
    
    public class Test01 {
    
    	public static void main(String[] args) {
    		
    		long addLong = addLong(10,20,(a,b)->a+b);
    		System.out.println(addLong);
    	}
    	
    	public static long addLong(long a,long b,BiFunction<Long,Long,Long> bf){
    		return bf.apply(a,b);
    	}
    }
    
    方法二、
    
    import java.util.function.BinaryOperator;
    
    public class Test01 {
    
    	public static void main(String[] args) {
    		
    		long addLong = addLong(10,20,(a,b)->a+b);
    		System.out.println(addLong);
    	}
    	
    	public static long addLong(long a,long b,BinaryOperator<Long> bo){
    		return bo.apply(a,b);
    	}
    } 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    2.创建I1接口,创建抽象方法:public String getValue(String str),在测试类中编写方法使用接口作为参数,将一个字符串转为大写,并作为方法的返回值
        
        方法一、
       import java.util.function.UnaryOperator;
    
    public class Test01 {
    
    	public static void main(String[] args) {
    		String strHandler = strHandler("abc", (str)->str.toUpperCase());
    		System.out.println(strHandler);
    	}
    	
    	public static String strHandler(String str,UnaryOperator<String> uo){
    		return uo.apply(str);
    	}
    }   
    
    方法二、
    import java.util.function.Function;
    
    public class Test01 {
    
    	public static void main(String[] args) {
    		
    		String strHandler = strHandler("abc",(str)->str.toUpperCase());
    		System.out.println(strHandler);
    	}
    	
    	public static String strHandler(String str,Function<String,String> fun){
    		return fun.apply(str);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    函数式接口的应用场景:

    在编写接口时,发现该接口只有一个抽象方法,就可以使用Java给我们提供过的函数式接口,

    好处:减少自己创建的接口

    四、方法、构造方法和数组引用

    方法、构造方法和数组引用就是Lamdba的另一种表现形式

    1.方法引用

    若Lamdba表达式中的内容由方法已经实现了,可以使用方法引用这个技能

    当你需要使用方法引用时,目标引用放在分隔符::前,方法的名称放在后面

    1.对象::实例方法

    Lambda表达式中调用方法的参数类型和返回值必须和函数式接口中的抽象方法一致

    public class Test01 {
    
    	public static void main(String[] args) {
    		
    //		I1 i1 = (str)->System.out.println(str);
    //		i1.method("abc");
    		
    		I1 i1 = System.out::println;
    		i1.method("abc");
    	}
    }
    
    interface I1{
    	public void method(String str);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    2.类名::静态方法
    import java.util.Comparator;
    public class Test01 {
    
    	public static void main(String[] args) {
    		
    //		Comparator comparator = (a,b)-> Integer.compare(a,b);
    //		System.out.println(comparator.compare(100,200));
    		
    		Comparator<Integer> comparator = Integer::compare;
    		System.out.println(comparator.compare(20, 20));
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    3.类名::实例方法

    Lambda表达式参数列表中第一个参数必须是实例方法的调用者

    Lambda表达式参数列表中第二个参数必须是实例方法的参数

    public class Test01 {
    
    	public static void main(String[] args) {
    		
    //		I1 i1 = (str1,str2)->str1.equals(str2);
    //		System.out.println(i1.method("abc1","abc2"));
    		
    		I1<String> i1 = String::equals;
    		System.out.println(i1.method("abc1", "abc1"));
    	}
    }
    
    interface I1<T>{
    	public boolean method(T t1,T t2);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2.构造方法的引用

    类名::new

    需要调用的构造方法的参数列表必须和函数式接口中抽象方法的参数列表一致

    public class Test01 {
    
    	public static void main(String[] args) {
    		
    //		I1 i1 = ()->new Student();
    //		Student stu1 = i1.method();
    
    		//调用无参构造创建学生对象
    		I1 i1 = Student::new;
    		Student stu1 = i1.method();
    		System.out.println(stu1);
    		
    //		I2 i2 = (name,age,salary,course)->new Student(name, age, salary, course);
    //		Student stu2 = i2.method("孙策", 25, 15000,Course.JAVA);
    //		System.out.println(stu2);
    		
    		//调用有参构造创建学生对象
    		I2 i2 = Student::new;
    		Student stu2 = i2.method("孙策", 25, 12000, Course.JAVA);
    		System.out.println(stu2);
    		
    	}
    }
    
    interface I1{
    	public Student method();
    }
    
    interface I2{
    	public Student method(String name,int age,double salary,Course course);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    public class Student {
    
    	private String name;
    	private int age;
    	private double salary;
    	private Course course;
    	
    	public Student() {
    	}
    
    	public Student(String name, int age, double salary, Course course) {
    		this.name = name;
    		this.age = age;
    		this.salary = salary;
    		this.course = course;
    	}
    
    	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 getSalary() {
    		return salary;
    	}
    
    	public void setSalary(double salary) {
    		this.salary = salary;
    	}
    
    	public Course getCourse() {
    		return course;
    	}
    
    	public void setCourse(Course course) {
    		this.course = course;
    	}
    
    	@Override
    	public String toString() {
    		return "Student [name=" + name + ", age=" + age + ", salary=" + salary + ", course=" + course + "]";
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    public enum Course {
    	JAVA,HTML,PYTHON;
    }
    
    • 1
    • 2
    • 3

    3.数组引用

    语法格式:type[]::new

    import java.util.Arrays;
    public class Test01 {
    
    	public static void main(String[] args) {
    		
    		I1<String[]> i1 =String[]::new;
    		String[] dd = i1.method(30);
    		System.out.println(Arrays.toString(dd));
    	}
    }
    
    interface I1<T>{
    	public T method(int length);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    五、Stream流

    1.概念

    Stream(流)是数据渠道,用于操作数据源(集合、数组等),生成元素序列。换言之,集合是存储数据的容器,流使用操作这些数据的

    Stream可以对集合进行非常复杂的查找、过滤、映射数据等操作,类似于SQL执行数据库查询。Stream提供了一种高效且易于使用的处理数据的方式

    注意:

    • Stream不会存储数据
    • Stream不会改变源数据,通过一系列操作数据源会返回一个持有结果的新Stream
    • Stream操作是延迟执行的,意味着流会等到需要结果的时候才执行

    2.执行步骤

    1. 创建Stream:通过数据源(集合、数组等)获取一个Stream
    2. 中间操作:中间操作链,对源数据的数据进行处理
    3. 终止操作:执行中间操作,并产生结果

    3.创建Stream对象

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.stream.Stream;
    
    import org.junit.Test;
    
    public class Test01 {
    
    	@Test
    	public void test01(){
    		//方式一:通过集合获取流对象
    
    		ArrayList<String> list = new ArrayList<>();
    		Collections.addAll(list, "aaa","bbb","ccc","ddd");
    		Stream<String> stream = list.stream();//获取此集合的Stream对象
    		stream.forEach(System.out::println);//遍历打印流中的数据
    	}
    	
    	@Test
    	public void test02(){
    		//方式二:通过数组获取流对象
    		String[] ss = {"aaa","bbb","ccc","ddd"};
    		Stream<String> stream = Arrays.stream(ss);//获取此数组的Stream对象
    		stream.forEach(System.out::println);//遍历打印流中的数据
    	}
    	
    	@Test
    	public void test03(){
    		//方式三:通过Stream的静态方法of()获取流对象
    		Stream<String> stream = Stream.of("ccc","bbb","aaa");//将元素添加到Stream对象中
    		stream.forEach(System.out::println);//遍历打印流中的数据
    	}
    	
    	@Test
    	public void test04(){
    		//方式四:创建无限流
    		Stream<Integer> stream = Stream.iterate(1, (x)->x+100);
    		stream = stream.limit(5);//获取流中前5条数据
    		stream.forEach(System.out::println);//遍历打印流中的数据
    	}
    	
    	@Test
    	public void test05(){
    		//方式五:创建无限流
    		Stream<Double> stream = Stream.generate(()->Math.random());//每次随机出一个数字
    		 stream = stream.limit(5);//获取流中前5条数据
    		 stream.forEach(System.out::println);//遍历打印流中的数据
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    4.中间操作 - 筛选与切片

    方法描述
    filter(Predicate p)从流中排除元素
    limit(long maxSize)设置限制数据条数
    skip(long n)跳过元素,返回跳过n个元素的流,若流中不满足n个元素则返回空流。与limit()互补
    distinct()筛选,流通过元素对象的hashCode()和equals()方法去除重复元素

    如果没有终止操作,中间操作就不会被调用,终止操作时一次性全部处理,这种称为惰性求值/延迟加载

    import java.util.Arrays;
    import java.util.List;
    
    import org.junit.Test;
    
    public class Test02 {
    
    	List<Student> stuList = Arrays.asList(
    			new Student("张三", 28, 4800,Course.JAVA),
    			new Student("李四", 36, 7200,Course.JAVA),
    			new Student("王五", 19, 9600,Course.HTML),
    			new Student("赵六", 42, 6100,Course.HTML),
    			new Student("孙七", 23, 9600,Course.PYTHON),
    			new Student("吴八", 31, 3000,Course.PYTHON),
       			new Student("李四", 36, 7200,Course.JAVA));
    	
    	@Test
    	public void test01(){
    		//需求1:过滤掉工资小于5000的学生对象
    		stuList.stream().filter((stu)->{
    			if(stu.getSalary() > 5000){
    				return true;
    			}
    			return false;
    		}).forEach(System.out::println);
    	}
    	
    	@Test
    	public void test02(){
    		//需求2:过滤掉工资小于5000的学生对象,并显示3条
    		stuList.stream().filter((stu)->{
    			if (stu.getSalary() > 5000) {
    				return true;
    			}
    			return false;
    		}).limit(3).forEach(System.out::println);
    	}
    	
    	
    	@Test
    	public void test03(){
    		//需求3:过滤掉小于5000的学生对象,并跳过第1个学生对象
    		stuList.stream().filter((stu)->{
    			if (stu.getSalary() > 5000) {
    				return true;
    			}
    			return false;
    		}).skip(1).forEach(System.out::println);
    	}
    	
    	@Test
    	public void test04(){
    	  //需求4:过滤掉小于5000的学生对象,并筛选掉重复元素
    	//底层是依据hashCode()和equals()来去判断两个对象是否相同
    		stuList.stream().filter((stu)->{
    			if (stu.getSalary() > 5000) {
    				return true;
    			}
    			return false;
    		}).distinct().forEach(System.out::println);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    public class Student implements Comparable<Student>{
    
    	private String name;
    	private int age;
    	private double salary;
    	private Course course;
    	
    	public Student() {
    	}
    	
    	public Student(String name, int age, double salary, Course course) {
    		this.name = name;
    		this.age = age;
    		this.salary = salary;
    		this.course = course;
    	}
    
    
    
    	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 getSalary() {
    		return salary;
    	}
    
    	public void setSalary(double salary) {
    		this.salary = salary;
    	}
    
    	public Course getCourse() {
    		return course;
    	}
    
    	public void setCourse(Course course) {
    		this.course = course;
    	}
    	
    	
    
    	@Override
    	public String toString() {
    		return "Student [name=" + name + ", age=" + age + ", salary=" + salary + ", course=" + course + "]";
    	}
    
    	@Override
    	public int hashCode(){
    		final int prime = 31;
    		int result = 1;
    		result = prime * result + age;
    		result = prime * result + ((course == null) ? 0 : course.hashCode());
    		result = prime * result + ((name == null) ? 0 : name.hashCode());
    		long temp;
    		temp = Double.doubleToLongBits(salary);
    		result = prime * result + (int)(temp ^ (temp >>> 32) );
    		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(course != other.course)
    			return false;
    		if (name == null) {
    			if (other.name != null) 
    				return false;
    		} else if(!name.equals(other.name))
    			return false;
    		if(Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
    			return false;
    		return true;
    	}
    	@Override
    	public int compareTo(Student o) {
    		if(this == o){
    			return 0;
    		}
    		if (this.age != o.age) {
    			return Integer.compare(this.age, o.age);
    		}
    		return 1;
    	}
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    public enum Course {
    
    	JAVA,HTML,PYTHON;
    }
    
    • 1
    • 2
    • 3
    • 4

    5.中间操作 - 映射

    方法描述
    map(Function mapper)将流中所有元素映射成一个新的元素或者提取信息
    flatMap(Function> mapper)将流中的流整合(整合成平面/平铺流)
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.stream.Stream;
    
    import org.junit.Test;
    
    public class Test03 {
    	List<String> nameList = Arrays.asList("张三","李四","王五","赵六","孙七","吴八");	
    
    	List<Student> stuList = Arrays.asList(
    			new Student("张三", 28, 4800,Course.JAVA),
    			new Student("李四", 36, 7200,Course.JAVA),
    			new Student("王五", 19, 9600,Course.HTML),
    			new Student("赵六", 42, 6100,Course.HTML),
    			new Student("孙七", 23, 9600,Course.PYTHON),
    			new Student("吴八", 31, 3000,Course.PYTHON),
    			new Student("李四", 36, 7200,Course.JAVA));
    
    	@Test
    	public void test01(){
    		//map() - 将流中所有元素映射成一个新的元素 或者 提取信息
    
    		//方式1:映射成一个新的元素
    		//需求:将流中所有字符串拼接成新的字符串
    		nameList.stream().map((str)->str.charAt(0)).forEach(System.out::println);
    	}
    
    	@Test       //重要!!!!!!!
    	public void test02(){
    		//方式2:映射成提取信息
    		//需求:把原来流中的学生对象替换成学生姓名
    		stuList.stream().map((stu)->stu.getName()).forEach(System.out::println);
    	}
    
    	@Test
    	public void test03(){
    		//带着需求学flatMap()
    		//flatMap() - 将流中的流整合(整合成平面/平铺流)
    		//需求:将nameList里的字符串转换为字符输出
    
    		//解决方案1:使用map()完成需求,可以看到流里包含另外的流,非常麻烦
    //		Stream> stream = nameList.stream().map(Test03::getCharacterStream);
    //		stream.forEach((sm)->{
    //			sm.forEach(System.out::println);
    //		});
    		
    		//解决方案2:使用flatMap()完成需求,将流中的流一并整合
    		nameList.stream().flatMap((str)->getCharacterStream(str)).forEach(System.out::println);
    		
    	}
    
    	public static Stream<Character> getCharacterStream(String str){
    		char[] charArray = str.toCharArray();
    		ArrayList<Character> list = new ArrayList<>();
    		for (char c : charArray) {
    			list.add(c);
    		}
    		return list.stream();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61

    6.中间操作 - 排序

    方法解释
    sorted()使用元素原有排序规则 - Comparable
    sorted(Comparator comparator)使用自定义排序规则 - Comparator
    import java.util.Arrays;
    import java.util.List;
    
    import org.junit.Test;
    
    public class Test04 {
    
    	List<Student> stuList = Arrays.asList(
    			new Student("张三", 28, 4800,Course.JAVA),
    			new Student("李四", 36, 7200,Course.JAVA),
    			new Student("王五", 19, 9600,Course.HTML),
    			new Student("赵六", 42, 6100,Course.HTML),
    			new Student("孙七", 23, 9600,Course.PYTHON),
    			new Student("吴八", 31, 3000,Course.PYTHON),
       			new Student("李四", 36, 7200,Course.JAVA));
    	
    	@Test
    	public void test01(){
    		//使用元素原有排序规则(Comparable
            //需求:按照年龄排序
    		stuList.stream().sorted().forEach(System.out::println);
    	}
    	
    	@Test
    	public void test02(){
    		//使用自定义排序规则(Comparator
            //需求:按照工资排序
    		stuList.stream().sorted((stu1,stu2)->{
    			if(stu1 == stu2){
    				return 0;
    			}
    			if(stu1.getSalary() != stu2.getSalary()){
    				return Double.compare(stu1.getSalary(), stu2.getSalary());
    			}
    			return 1;
    		}).forEach(System.out::println);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    7.终止操作 - 匹配与查找

    方法描述
    allMatch(Predicate predicate)检查是否匹配所有元素
    anyMatch(Predicate predicate)检查是否匹配至少一个元素
    noneMatch(Predicate predicate)检查是否没有匹配所有元素
    findFirst()返回第一个元素
    findAny()返回任意一个元素(但效果不好)
    count()返回流中元素的个数
    max(Comparator comparator)返回流中最大值
    min(Comparator comparator)返回流中最小值
    import java.util.Arrays;
    import java.util.List;
    import java.util.Optional;
    
    import org.junit.Test;
    
    public class Test05 {
    
    	List<Student> stuList = Arrays.asList(
    			new Student("张三", 28, 4800,Course.JAVA),
    			new Student("李四", 36, 7200,Course.JAVA),
    			new Student("王五", 19, 9600,Course.HTML),
    			new Student("赵六", 42, 6100,Course.HTML),
    			new Student("孙七", 23, 9600,Course.PYTHON),
    			new Student("吴八", 31, 3000,Course.PYTHON),
       			new Student("李四", 36, 7200,Course.JAVA));
    	
    	@Test
    	public void test01(){
    		//需求1:检查流中所有元素是否匹配 工资>5000
    		boolean allMatch = stuList.stream().allMatch((stu)->{
    			if (stu.getSalary() > 5000) {
    				return true;
    			}
    			return false;
    		});
    		System.out.println(allMatch);
    	}
    	
    	@Test
    	public void tesst02(){
    		//需求2:检查流中所有元素至少匹配一个 工资>5000
    		boolean anyMatch = stuList.stream().anyMatch((stu)->{
    			if (stu.getSalary() > 5000) {
    				return true;
    			}
    			return false;
    		});
    		System.out.println(anyMatch);
    	}
    	
    	@Test
    	public void test03(){
    		//需求3:检查流中所有元素是否没有匹配 工资>5000
    		boolean noneMatch = stuList.stream().noneMatch((stu)->{
    			if (stu.getSalary() > 5000) {
    				return true;
    			}
    			return false;
    		});
    		System.out.println(noneMatch);
    	}
    	
    	@Test
    	public void test04(){
    		//需求4:返回工资最高的学生信息
    		//Optional是一个容器,该容器中存储了学生对象
    		Optional<Student> max = stuList.stream().max((stu1,stu2)->{
    			return Double.compare(stu1.getSalary(), stu2.getSalary());
    		});
    		System.out.println(max.get());
    	}
    	
    	@Test
    	public void test05(){
    		//需求5:返回工资最低的学生信息
    		//Optional是一个容器,该容器中存储了学生对象
    		Optional<Student> min = stuList.stream().min((stu1,stu2)->{
    			return Double.compare(stu1.getSalary(), stu2.getSalary());
    		});
    		System.out.println(min.get());
    	}
    	
    	@Test
    	public void test06(){
    		//需求6:返回随机学生信息(但效果不好)
    		Optional<Student> findAny = stuList.stream().findAny();
    		Student stu = findAny.get();
    		System.out.println(stu);
    	}
    	
    	@Test
    	public void test07(){
    		//需求6:获取学生个数
    		long count = stuList.stream().count();
    		System.out.println(count);
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
  • 相关阅读:
    [科研琐事] 安装服务器的二三事
    【Linux】Linux工具——yum,vim
    Linux项目自动化构建工具-make/Makefile
    探索古彝文的秘密,AI实现古籍传承
    诡异,明明更新成功了状态,查不出来了
    25.gateway的Filter 过滤器工厂(springcloud)
    Nginx -3
    iText实战--Table、cell 和 page event
    信号处理中简单实用的方法——提取信号中的包络
    从零实现深度学习框架——再探多层双向RNN的实现
  • 原文地址:https://blog.csdn.net/GL280599ZL/article/details/127706585