首页 > 其他分享 >JDK1.8 新特性

JDK1.8 新特性

时间:2023-03-02 09:22:05浏览次数:32  
标签:JDK1.8 System 特性 Person println import public out

3.1 Lambda表达式

3.1.1 概念

​ Lambda是一个匿名函数,可以理解为一段可以传递的代码(将代码像数据一样传递);可以写出更简洁、更灵活的代码;作为一种更紧凑的代码风格,是Java语言表达能力得到提升。

3.1.2 匿名内部类

​ 需求:把对象放入集合并按照年龄排序

package com.aaa.jdk8nf.lambda;

import lombok.AllArgsConstructor;

import lombok.Data;

import lombok.NoArgsConstructor;

/**

 \* @ fileName:Person

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/12 14:10

 \* @ version:1.0.0

 */

@Data

@AllArgsConstructor

@NoArgsConstructor

public class Person {

​    private String name;

​    private int age;

//    @Override

//    public int compareTo(Person o) {

//        return this.age-o.getAge();

//    }

}

package com.aaa.jdk8nf.lambda;

import java.util.Comparator;

import java.util.TreeSet;

/**

 \* @ fileName:AnonymousInternalClass

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/12 14:13

 \* @ version:1.0.0

 */

public class AnonymousInternalClass {

​    public static void main(String[] args) {

​        Person person1 = new Person("赵一",28);

​        Person person2 = new Person("钱二",18);

​        Person person3 = new Person("孙三",8);

​        Person person4 = new Person("李四",38);

​        TreeSet<Person>  personTreeSet = new TreeSet<>(new Comparator<Person>() {

​            @Override

​            public int compare(Person o1, Person o2) {

​                return o1.getAge()-o2.getAge();

​            }

​        });

​        personTreeSet.add(person1);

​        personTreeSet.add(person2);

​        personTreeSet.add(person3);

​        personTreeSet.add(person4);

​        System.out.println(personTreeSet);

​    }

}


3.1.3 lambda语法及实例

语法及简单示例:

Lmabda表达式的语法总结: () -> {};

λ表达式有三部分组成:参数列表,箭头(->),以及一个表达式或语句块。

前置 语法
无参数无返回值 () -> System.out.println(“Hello World”)
有一个参数无返回值 (x) -> System.out.println(x)
有且只有一个参数无返回值 x -> System.out.println(x)
有多个参数,有返回值,有多条lambda体语句 (x,y) -> {System.out.println(“xxx”);return xxxx;};
有多个参数,有返回值,只有一条lambda体语句 (x,y) -> xxxx

实例:

package com.aaa.nf.lambda;

import java.util.Comparator;

import java.util.TreeSet;

/**

 \* @ fileName:TreeSetTest

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2023/2/18 14:41

 \* @ version:1.0.0

 */

public class TreeSetTestUseInnerLambdaClass {

​    public static void main(String[] args) {

​        Person person1 = new Person("马1云",18);

​        Person person2 = new Person("马2云",19);

​        Person person3 = new Person("马3云",14);

​        Person person4 = new Person("马4云",14);

​        TreeSet<Person> treeSet  = new TreeSet<Person>((Person o1, Person o2) -> o1.getAge()-o2.getAge()==0?o1.getName().hashCode()-o2.getName().hashCode():o1.getAge()-o2.getAge());

​       // TreeSet<Person> treeSet1  = new TreeSet<Person>((Person o1, Person o2) ->{return o1.getAge()-o2.getAge()==0?o1.getName().hashCode()-o2.getName().hashCode():o1.getAge()-o2.getAge();});

​        //在TreeSet中添加的对象必须实现比较器接口

​        treeSet.add(person1);

​        treeSet.add(person2);

​        treeSet.add(person3);

​        treeSet.add(person4);

​        //ClassCastException 类转换异常

​        System.out.println(treeSet);

​    }

}

多线程lambda示例:

package com.aaa.nf.lambda;

import java.util.Random;

import java.util.UUID;

import java.util.concurrent.Callable;

import java.util.concurrent.FutureTask;

/**

 \* @ fileName:MultiThreadLambdaTest

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2023/2/18 15:08

 \* @ version:1.0.0

 */

public class MultiThreadLambdaTest {

​    public static void main(String[] args) {

​        //匿名内部类写法Runnable

​        new Thread(new Runnable(){

​            @Override

​            public void run() {

​                System.out.println(Thread.currentThread().getName()+"启动了。。。。");

​            }

​        }).start();

​        //匿名内部类写法Runnable   lambda写法

​        new Thread(()->System.out.println(Thread.currentThread().getName()+"启动了。。。。")).start();

​       //匿名内部类写法Callable

​        new Thread(new FutureTask<>(new Callable<Object>() {

​            @Override

​            public Object call() throws Exception {

​                System.out.println(Thread.currentThread().getName()+"启动了。。。。");

​                return 1;

​            }

​        })).start();

​        //匿名内部类写法Callable  lambda写法

​        new Thread(new FutureTask<>(()->{System.out.println(Thread.currentThread().getName()+"启动了。。。。");

​                                        return 1;})

​                 ).start();

​    }

}

重要特征及示例:

以下是lambda表达式的重要特征:

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。

  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。

  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。

  • 可选的返回关键字return:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。

// 1. 不需要参数,返回值为 5  

() -> 5  

  

// 2. 接收一个参数(数字类型),返回其2倍的值  

x -> 2 * x  

  

// 3. 接受2个参数(数字),并返回他们的差值  

(x, y) -> x – y  

  

// 4. 接收2个int型整数,返回他们的和  

(int x, int y) -> x + y  

  

// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  

(String s) -> System.out.print(s)

实现:

package com.aaa.jdk8nf.lambda;

/**

 \* @ fileName:CalcInterface

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/12 14:34

 \* @ version:1.0.0

 */

public interface CalcInterface {

​    /**

​     \* 运算接口

​     \* @param a

​     \* @param b

​     \* @return

​     */

​    int calc(int a,int b);

}

package com.aaa.jdk8nf.lambda;

/**

 \* @ fileName:CalcImpl
 \* @ description:
 \* @ author:zhz
 \* @ createTime:2022/10/12 14:36
 \* @ version:1.0.0
 */

public class CalcImpl {
    /**
     \* 封装运算方法
    \* @param a
     \* @param b
     \* @param calcInterface
    \* @return
    */
​    public static  int  work(int a,int b,  CalcInterface calcInterface){

​        return calcInterface.calc(a,b);

​    }

​    public static void main(String[] args) {

​        CalcInterface add = new CalcInterface() {

​            @Override

​            public int calc(int a, int b) {

​                return a+b;

​            }

​        };

​        System.out.println(add.calc(1,2));

​        System.out.println("--------------------------------");

​        CalcInterface add1 = (a,b) -> a+b;

​        System.out.println(add1.calc(1,2));

​        CalcInterface subtract = (a,b)->a-b;

​        System.out.println(subtract.calc(1,2));

​        CalcInterface multiple = (a,b)->a*b;

​        System.out.println(multiple.calc(1,2));

​        CalcInterface divide = (a,b)->a/b;

​        System.out.println(divide.calc(4,2));

​        System.out.println("----------------------------");

​        System.out.println(work(4,2,(a,b)->a/b));

​        System.out.println(work(4,2,(a,b)->a+b));

​        System.out.println(work(4,2,(a,b)->a-b));

​    }

}


3.1.4 变量作用域

一个局部变量如果要在匿名类或是 Lambda 表达式中访问,那么这个局部变量必须是 final 的,即使没有修饰为 final 类型,编译器也会自动加上 final 修饰符。

package com.aaa.jdk8nf.lambda;

/**

 \* @ fileName:CalcImpl

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/12 14:36

 \* @ version:1.0.0

 */

public class CalcImpl {

​    /**

​     \* 封装运算方法

​     \* @param a

​     \* @param b

​     \* @param calcInterface

​     \* @return

​     */

​    public static  int  work(int a,int b,  CalcInterface calcInterface){

​        return calcInterface.calc(a,b);

​    }

​    public static void main(String[] args) {

​        System.out.println("--------------------------------");

​         int c = 11;

//        CalcInterface add = new CalcInterface() {

//            @Override

//            public int calc(int a, int b) {

//                 c = a+b;

//                return c;

//            }

//        };

//        System.out.println(add.calc(1,2));

​        CalcInterface add1 = (a,b) -> {

​            // c =1;

​            System.out.println(c+"-------------------------------");

​            return a+b;

​        };

​        System.out.println(add1.calc(1,2));

​        CalcInterface subtract = (a,b)->a-b;

​        System.out.println(subtract.calc(1,2));

​        CalcInterface multiple = (a,b)->a*b;

​        System.out.println(multiple.calc(1,2));

​        CalcInterface divide = (a,b)->a/b;

​        System.out.println(divide.calc(4,2));

​        System.out.println("----------------------------");

​        System.out.println(work(4,2,(a,b)->a/b));

​        System.out.println(work(4,2,(a,b)->a+b));

​        System.out.println(work(4,2,(a,b)->a-b));

​    }

}

3.2 函数式接口

3.2.1 概念

​ 一个接口中的抽象方法只有一个,那么这个接口就是一个函数式接口

这种类型的接口也称为SAM接口,即Single Abstract Method interfaces

img

jdk8 java.util.function包

3.2.2 特点

接口有且仅有一个抽象方法

允许定义静态方法

允许定义默认方法 default

允许含有java.lang.Object中的public方法

@FunctionInterface 该注解不是必须的,如果一个接口符合"函数式接口"定义,那么加不加该注解都没有影响。加上该注解能够更好地让编译器进行检查。如果编写的不是函数式接口,但是加上了@FunctionInterface,那么编译器会报错

3.2.3 常见函数式接口案例

1)supplier

supplier 供给型接口, 无参数,有返回值,返回泛型T的对象。

使用Supplier产生一个指定长度的整型数组

package com.aaa.jdk8nf.sam;

import java.util.Date;

import java.util.Random;

import java.util.function.Supplier;

/**

 \* @ fileName:SupplierDemo

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/10 9:10

 \* @ version:1.0.0

 */

public class SupplierDemo {

​    public SupplierDemo() {

​        System.out.println(hashCode());

​    }

​    /**

​     \* 使用Supplier产生一个指定长度的整型数组

​     \* @param length

​     \* @param integerSupplier

​     \* @return

​     */

​    public static  int[]   createFixedLengthIntArrayUseSupplier(int length,Supplier<Integer> integerSupplier){

​        int[] intArray  = new int[length];

​        for (int i = 0; i < intArray.length; i++) {

​             intArray[i]=integerSupplier.get();

​        }

​        return intArray;

​    }

​    public static void main(String[] args) {

​        Supplier<SupplierDemo> supplierDemoSupplier =()->new SupplierDemo();

​        SupplierDemo supplierDemo = supplierDemoSupplier.get();

​        System.out.println(supplierDemo);

​        Supplier<Date> dateSupplier =()->new Date();

​        Date date = dateSupplier.get();

​        System.out.println(date);

​        System.out.println("--------------------------");

​        Random random = new Random();

​        int[] intArray = createFixedLengthIntArrayUseSupplier(20, () -> random.nextInt(100));

​        for (int i : intArray) {

​            System.out.print(i+" ");

​        }

​    }

}

2) consumer

Consumer 消费型接口,有参数T,无返回值,对类型T的操作

需求:按需要处理字符串并打印

package com.aaa.jdk8nf.sam;

import java.util.function.Consumer;

/**

 \* @ fileName:ConsumerDemo

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/10 9:25

 \* @ version:1.0.0

 */

public class ConsumerDemo {

​    /**

​     \* 按照需求处理任意字符串

​     \* @param str

​     \* @param stringConsumer

​     */

​    public static  void handlerString(String str,Consumer<String> stringConsumer){

​        stringConsumer.accept(str);

​    }

​    public static void main(String[] args) {

​      /*  Consumer<String>  stringConsumer1 = new Consumer<String>() {

​            @Override

​            public void accept(String s) {

​                System.out.println(s.toUpperCase());

​            }

​        };*/

​       //转大写打印

​        Consumer<String>  stringConsumer1 = s-> System.out.println(s.toUpperCase());

​        stringConsumer1.accept("hello");

​        //获取字符串长度并打印

​        Consumer<String>  stringConsumer2 = s-> System.out.println(s.length());

​        stringConsumer2.accept("hello");

​        handlerString("hello world",s-> System.out.println(s.toUpperCase()));

​        handlerString("hello world",s-> System.out.println(s.length()));

​        //截取字符串打印

​        handlerString("hello world",s-> System.out.println(s.substring(0,5)));

​    }

}

默认实现方法:andThen方法的入参和返回值都是consumer类型的时候,可以使用andThen,在消费数据的时候,多次对数据进行增强处理。

需求:既要把字符串转大写打印,还要计算长度打印,还要截取字符串打印

package com.aaa.jdk8nf.sam;

import java.util.function.Consumer;

/**

 \* @ fileName:ConsumerDemo

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/10 9:25

 \* @ version:1.0.0

 */

public class ConsumerAndThenDemo {

​    /**

​     \* 按照需求多次处理任意字符串

​     \* @param str

​     \* @param stringConsumer

​     */

​    public static  void handlerString(String str,Consumer<String> stringConsumer,Consumer<String> stringConsumer1,Consumer<String> stringConsumer2){

​        stringConsumer.andThen(stringConsumer1).andThen(stringConsumer2).accept(str);

​    }

​    public static void main(String[] args) {

//        handlerString("hello world",s-> System.out.println(s.toUpperCase()));

//        handlerString("hello world",s-> System.out.println(s.length()));

//        //截取字符串打印

//        handlerString("hello world",s-> System.out.println(s.substring(0,5)));

​        handlerString("hello world",s-> System.out.println(s.toUpperCase()),

​                s-> System.out.println(s.length()),

​                s-> System.out.println(s.substring(0,5)));

​    }

}

3) predicate

​ Predicate 断言型接口,有参数T,返回boolean,判断类型T是否满足条件返回boolean

​ 需求:判断一个人是否符合做你女/男朋友(根据性别判断)

package com.aaa.jdk8nf.sam;

import java.util.function.Predicate;

/**

 \* @ fileName:PredicateDemo

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/10 9:43

 \* @ version:1.0.0

 */

public class PredicateDemo {

​    /**

​     \* 判断是否符合做女朋友

​     \* @param person

​     \* @param personPredicate

​     \* @return

​     */

​    public static boolean testIsTrueGetGirlFriend(Person person,Predicate<Person> personPredicate){

​        return personPredicate.test(person);

​    }

​    public static void main(String[] args) {

​          Person person =new Person("赵漂亮",18,"女");

​        /*Predicate<Person> personPredicate = new Predicate<Person>() {

​            @Override

​            public boolean test(Person person) {

​                return "女".equals(person.getSex());

​            }

​        };*/

​         Predicate<Person> personPredicate = p->"女".equals(p.getSex());

​        boolean isTrue = personPredicate.test(person);

​        System.out.println(isTrue ?"符合":"不符合");

​        System.out.println("---------------------------");

​        boolean isTrue1 =testIsTrueGetGirlFriend(person,p->"女".equals(p.getSex()));

​        System.out.println(isTrue1 ?"符合":"不符合");

​    }

}

​ and方法 逻辑与 多个条件共同满足。

package com.aaa.jdk8nf.sam;

import java.util.function.Predicate;

/**

 \* @ fileName:PredicateDemo

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/10 9:43

 \* @ version:1.0.0

 */

public class PredicateAndDemo {

​    /**

​     \* 判断是否符合做女朋友  and多个条件共同判断

​     \* @param person

​     \* @param personPredicate

​     \* @return

​     */

​    public static boolean testIsTrueGetGirlFriend(Person person,Predicate<Person> personPredicate

​            ,Predicate<Person> personPredicate1

​            ,Predicate<Person> personPredicate2){

​        return personPredicate.and(personPredicate1).and(personPredicate2).test(person);

​    }

​    public static void main(String[] args) {

​          Person person =new Person("赵漂亮",18,"女");

​        boolean isTrue1 =testIsTrueGetGirlFriend(person,p->"女".equals(p.getSex()),

​                p->p.getAge()>=18,

​                p->p.getName().contains("漂亮"));

​        System.out.println(isTrue1 ?"符合":"不符合");

​    }

}

or方法 逻辑或,满足任一条件即可。

package com.aaa.jdk8nf.sam;

import java.util.function.Predicate;

/**

 \* @ fileName:PredicateDemo

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/10 9:43

 \* @ version:1.0.0

 */

public class PredicateOrDemo {

​    /**

​     \* 判断是否符合做女朋友  and多个条件共同判断

​     \* @param person

​     \* @param personPredicate

​     \* @return

​     */

​    public static boolean testIsTrueGetGirlFriend(Person person,Predicate<Person> personPredicate

​            ,Predicate<Person> personPredicate1

​            ,Predicate<Person> personPredicate2){

​        return personPredicate.or(personPredicate1).or(personPredicate2).test(person);

​    }

​    public static void main(String[] args) {

​          Person person =new Person("赵美丽",18,"男");

​        boolean isTrue1 =testIsTrueGetGirlFriend(person,p->"女".equals(p.getSex()),

​                p->p.getAge()>=18,

​                p->p.getName().contains("漂亮"));

​        System.out.println(isTrue1 ?"符合":"不符合");

​    }

}



4) function

​ function<T,R> 函数型(转换行)接口,有参数T,有返回值R,对类型T对象操作,返回R类型的对象。

​ 需求:输入一个对象集合,转换获取一个对象名称集合

package com.aaa.jdk8nf.sam;

import java.util.ArrayList;

import java.util.List;

import java.util.function.Function;

/**

 \* @ fileName:FunctionDemo

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/12 16:09

 \* @ version:1.0.0

 */

public class FunctionDemo {

​    /**

​     \* 把人员集合转换为人员名称集合

​     \* @param personList

​     \* @param personStringFunction

​     \* @return

​     */

​    public static List<String> personListToPersonNameList(List<Person> personList, Function<Person,String> personStringFunction){

​        List<String> nameStringList = new ArrayList<>();

​        for (Person person : personList) {

​            nameStringList.add(personStringFunction.apply(person));

​        }

​        return nameStringList;

​    }

​    public static void main(String[] args) {

​        Person person1 = new Person("赵美丽1",29,"女");

​        Person person2 = new Person("赵美丽2",19,"女");

​        Person person3 = new Person("赵美丽3",39,"女");

​        Person person4 = new Person("赵美丽4",9,"女");

​        Person person5 = new Person("赵美丽5",18,"女");

​        List<Person> personList = new ArrayList<>();

​        personList.add(person1);

​        personList.add(person2);

​        personList.add(person3);

​        personList.add(person4);

​        personList.add(person5);

​        List<String> stringList = personListToPersonNameList(personList, p -> p.getName());

​        System.out.println(stringList);

​    }

}

compose和andThen 都是多个处理函数的组合,区别是在当前函数执行前后

package com.aaa.jdk8nf.sam;

import java.util.ArrayList;

import java.util.List;

import java.util.function.Function;

/**

 \* @ fileName:FunctionDemo

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/10 10:01

 \* @ version:1.0.0

 */

public class FunctionComposeAndThenDemo {

​    /**

​     \*  测试compose和andthen区别

​     \* @param i

​     \* @param integerFunction1

​     \* @param integerFunction2

​     \* @return

​     */

​    public static int  composeExecute(int i,Function<Integer,Integer> integerFunction1,

​                                        Function<Integer,Integer> integerFunction2){

​        //在调用Function1之前会先调用Function2

​        return integerFunction1.compose(integerFunction2).apply(i);

​    }

​    /**

​     \*  测试compose和andthen区别

​     \* @param i

​     \* @param integerFunction1

​     \* @param integerFunction2

​     \* @return

​     */

​    public static int  andThenExecute(int i,Function<Integer,Integer> integerFunction1,

​                                      Function<Integer,Integer> integerFunction2){

​        //在调用Function1之后再调用Function2

​        return integerFunction1.andThen(integerFunction2).apply(i);

​    }

​    public static void main(String[] args) {

​        int i1 = composeExecute(3, i -> 2 * i, i -> i * i);

​        System.out.println(i1);

​        int i2 = andThenExecute(3, i -> 2 * i, i -> i * i);

​        System.out.println(i2);

​    }

}

3.2.4 自定义函数式接口

1)定义接口

package com.aaa.jdk8nf.sam;

/**

 \* @ fileName:CustomPrintMessage

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/10 10:42

 \* @ version:1.0.0

 */

@FunctionalInterface

public interface CustomPrintMessage<A> {

​    /**

​     \* 打印任何方法

​     \* @param t

​     */

​    void printAnyThing(A t);

​    //void printAnyThing1(A t);

​    /**

​     \* 可以有使用default修饰的方法

​     */

​    default void  mehthodA(){

​        System.out.println("可以有default方法");

​    };

​    /**

​     \* 可以有使用static的方法

​     */

​    static void methodB(){

​        System.out.println("可以有static方法");

​    }

​    /**

​     \* 也可以含有java.lang.Object的public方法

​     \* @param obj

​     \* @return

​     */

​    boolean equals(Object obj);

​    /**

​     \* 也可以含有java.lang.Object的public方法

​     \* @return

​     */

​    String toString();

}

2)接口使用:

package com.aaa.jdk8nf.sam;

/**

 \* @ fileName:CustomPrintMessageTest

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/10 10:47

 \* @ version:1.0.0

 */

public class CustomPrintMessageTest {

​    /**

​     \* 自定义函数接口的使用

​     \* @param person

​     \* @param personCustomPrintMessage

​     */

​    public static void  printPerson(Person person,CustomPrintMessage<Person> personCustomPrintMessage){

​        personCustomPrintMessage.printAnyThing(person);

​    }

​    public static void main(String[] args) {

​        Person person1 =new Person("赵漂亮1",28,"女");

​        printPerson(person1,p-> System.out.println(p));

​    }

}

3.3 方法引用

3.3.1 概念及作用

概念:

方法引用是jdk8推出的一个新特性,在一定的条件下可以替换lambda表达式,可以理解为方法引用实际上还是一个lambda表达式。

作用:

旨在编写更加简洁紧凑的代码风格,提高代码重用率(不提高执行效率)。

3.3.2 语法 ::

类型Class 方法引用 lambda表达式
静态方法引用 类名::method (args)->类名.method(args)
实例方法引用 实例::method (args)->实例.method(args)
实例方法引用 类名::method (inst,args)->类名.method(args)
构造方法引用 类名::new (args)->new 类名(args)

(函数式)接口类型 对象变量名 = 对象::被引用的实例方法;

(函数式)接口类型 对象变量名 = 类名::被引用的静态方法;

(函数式)接口类型 对象变量名 = 类名::被引用的实例方法;

(函数式)接口类型 对象变量名 = 类名::new(引用的是类的构造方法);

“=”号左边函数式接口抽象方法的参数列表、返回值类型需要与右边被引用的方法的参数列表、返回值类型一致。

注意:方法引用旨在简化lambda表达式写法,在lambda表达式的基础上使用,不能脱离lambda表达式单独使用(lambda表达式依赖函数式接口)。

3.3.3 代码示例

person:

package com.aaa.jdk8nf.methodref;

import java.util.function.Supplier;

/**

 \* @ fileName:Person

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/12 16:39

 \* @ version:1.0.0

 */

public class Person {

​    private String name;

​    private int age;

​    

​    public Person() {

​    }

​    public Person(String name, int age) {

​        this.name = name;

​        this.age = age;

​    }

​    /**

​     \* 借助供给型接口Supplier 创建Person对象

​     \* @param personSupplier

​     \* @return

​     */

​    public static  Person createPerson(Supplier<Person> personSupplier){

​       return personSupplier.get();

​    }

​    /**

​     \* 静态打印方法

​     \* @param person

​     */

​    public static void staticPrint(Person person){

​        System.out.println(person);

​    }

​    /**

​     \* 带参普通打印方法

​     \* @param person

​     */

​    public   void print(Person person){

​        System.out.println(person);

​    }

​    /**

​     \* 不带参数普通打印方法

​     */

​    public void print(){

​        System.out.println("不带参数打印方法");

​    }

​    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;

​    }

​    @Override

​    public String toString() {

​        return "Person{" +

​                "name='" + name + '\'' +

​                ", age=" + age +

​                '}';

​    }

}

测试

package com.aaa.jdk8nf.methodref;

import java.io.PrintStream;

import java.util.ArrayList;

import java.util.List;

import java.util.function.BiFunction;

/**

 \* @ fileName:MethodReferenceDemo

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/12 16:44

 \* @ version:1.0.0

 */

public class MethodReferenceDemo {

​    public static void main(String[] args) {

​        //类::new   调用构造方法

​        System.out.println("--------------使用lambda表达式调用构造方法--------------");

​        Person person1  =  Person.createPerson(()->new Person());

​        System.out.println(person1);

​        System.out.println("--------------使用方法引用调用构造方法--------------");

​        Person person2  =  Person.createPerson(Person::new);

​        //Person person3 = Person::new;  //错误 必须在lambda基础上使用  不能单独使用

​        System.out.println(person2);

​        /*BiFunction<String,Integer,Person> biFunction1 = new BiFunction<String, Integer, Person>() {

​            @Override

​            public Person apply(String s, Integer integer) {

​                return new Person(s,integer);

​            }

​        };*/

​       // BiFunction<String,Integer,Person> biFunction2 = (s,i)->new Person(s,i);

​        // BiFunction 两个输入参数  一个返回值    和当前构造匹配 就可以使用它,进行方法引用调用

​        BiFunction<String,Integer,Person> biFunction = Person::new;

​        Person person3 = biFunction.apply("王五1", 18);

​        Person person4 = biFunction.apply("王五2", 28);

​        Person person5 = biFunction.apply("王五3", 38);

​        List<Person> personList = new ArrayList<>();

​        personList.add(person3);

​        personList.add(person4);

​        personList.add(person5);

​        //类::静态方法

​        System.out.println("--------------使用lambda表达式调用静态方法--------------");

​        personList.forEach(p-> System.out.println(p));

​        System.out.println("--------------使用方法引用调用静态方法--------------");

​        personList.forEach(Person::staticPrint);

​      

​        //对象::普通方法

​        System.out.println("-------使用方法引用调用静态方法System.out.print---------");

​        /*PrintStream out = System.out;

​        personList.forEach(out::println);*/

​        personList.forEach(System.out::println);

​        System.out.println("--------------使用方法引用调用非静态方法--------------");

​        personList.forEach(person5::print);

​        //类::普通方法

​        System.out.println("--------------使用方法引用调用非静态方法--------------");

​        personList.forEach(Person::print);

​    }

}



3.4 stream API

3.4.1 概念及作用

概念:

Stream 是Java8中处理集合的关键抽象概念,它可以对集合进行非常复杂的查找、过滤、筛选等操作,在新版的JPA【连接数据库】中,也已经加入了Stream。

作用:

​ Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

注意事项:

一个stream只能操作一次

stream流返回的是新的流

只有调用终结方法stream的中间操作才会执行

3.4.2 流生成

1)stream:所有的 Collection 集合都可以通过 stream 默认方法获取流(顺序流);

2)parallelStream:所有的 Collection 集合都可以通过parallelStream获取并行流

3)Stream.of:Stream 接口的静态方法 of 可以获取数组对应的流。

4)Arrays.stream: Arrays的静态方法stream也可以获取流

package com.aaa.jdk8nf.stream;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

import java.util.stream.Stream;

/**

 \* @ fileName:StreamCreate

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/10 11:33

 \* @ version:1.0.0

 */

public class StreamCreate {

    public static void main(String[] args) {

        List<String> stringList = new ArrayList<>();

        stringList.add("zhaoyi");

        stringList.add("qianer");

        stringList.add("sunsan");

        stringList.add("lisi");

        //打印

        stringList.forEach(System.out::println);

        //1,任何集合对象中都有stream()

        Stream<String> stream = stringList.stream();

        //2,任何集合对象中都有 parallelStream()

        Stream<String> stringStream = stringList.parallelStream();

        //3,通过Stream 的of方法产生

        Stream<String> stream1 = Stream.of("a", "b", "c", "d");

        //4,通过Arrays工具类 产生类

        String[] strArrray = {"a", "b", "c", "d"};
        Stream<String> stream2 = Arrays.stream(strArrray);

    }

}

3.4.3 常用方法

1)forEach

​ 终结方法 用来遍历流中的数据

需求: 循环遍历StringList集合

package com.aaa.newfeature.stream;

import java.util.ArrayList;

import java.util.Arrays;

import java.util.List;

import java.util.stream.Stream;

/**

 \* @ fileName:StreamCreate

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/9/26 21:55

 \* @ version:1.0.0

 */

public class StreamForEach {

    public static void main(String[] args) {

        List<String> stringList = new ArrayList<>();

        stringList.add("zhaoyi");

        stringList.add("qianer");

        stringList.add("sunsan");

        stringList.add("lisi");

        Stream<String> stream = stringList.stream();

        stream.forEach(s-> System.out.println(s));

        stream.forEach(System.out::println);

    }

}

2)map

非终结方法 将流中的元素映射到另一个流中。该接口需要一个 Function 函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。

需求:把所有用户名转大写并输出

package com.aaa.newfeature.stream;

import java.util.ArrayList;

import java.util.List;

import java.util.stream.Stream;

/**

 \* @ fileName:StreamCreate

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/9/26 21:55

 \* @ version:1.0.0

 */

public class StreamMap {

​    public static void main(String[] args) {

​        List<String> stringList = new ArrayList<>();

​        stringList.add("zhaoyi");

​        stringList.add("qianer");

​        stringList.add("sunsan");

​        stringList.add("lisi");

​        Stream<String> stream = stringList.stream().map((s)->{return s.toUpperCase();});

​        stream.forEach(System.out::println);

​        stream.close();

​    }

}

3)filter

非终结方法 用于过滤数据,返回符合过滤条件的数据,将一个流转换成另一个子集流。

需求:找出人员表中年龄大于18岁的人,并打印

package com.aaa.newfeature.stream;

import com.aaa.newfeature.methodref.Person;

import java.util.ArrayList;

import java.util.List;

import java.util.function.BiFunction;

import java.util.stream.Stream;

/**

 \* @ fileName:StreamCreate

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/9/26 21:55

 \* @ version:1.0.0

 */

public class StreamFilter {

​    public static void main(String[] args) {

​        //调用带参构造

​        //BiFunction表示接受两个参数并产生结果的函数

​        BiFunction<String,Integer, Person> personBiFunction=Person::new;

​        Person person1 = personBiFunction.apply("孙三", 10);

​        Person person2 = personBiFunction.apply("李四", 20);

​        Person person3 = personBiFunction.apply("王五", 12);

​        Person person4 = personBiFunction.apply("马六", 21);

​        List<Person> personList = new ArrayList<>();

​        personList.add(person1);

​        personList.add(person2);

​        personList.add(person3);

​        personList.add(person4);

​        Stream<Person> stream = personList.stream().filter(p->{return p.getAge()>18;});

​        stream.forEach(System.out::println);

​        stream.close();

​    }

}

4)limit

非终结方法 limit(int maxSize) 返回由此流的元素组成的流,截短长度不能超过 maxSize 。

package com.aaa.newfeature.stream;

import com.aaa.newfeature.methodref.Person;

import java.util.ArrayList;

import java.util.List;

import java.util.function.BiFunction;

import java.util.stream.Stream;

/**

 \* @ fileName:StreamCreate

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/9/26 21:55

 \* @ version:1.0.0

 */

public class StreamLimit {

​    public static void main(String[] args) {

​        //调用带参构造

​        //BiFunction表示接受两个参数并产生结果的函数

​        BiFunction<String,Integer, Person> personBiFunction=Person::new;

​        Person person1 = personBiFunction.apply("孙三", 10);

​        Person person2 = personBiFunction.apply("李四", 20);

​        Person person3 = personBiFunction.apply("王五", 12);

​        Person person4 = personBiFunction.apply("马六", 21);

​        List<Person> personList = new ArrayList<>();

​        personList.add(person1);

​        personList.add(person2);

​        personList.add(person3);

​        personList.add(person4);

​        Stream<Person> stream = personList.stream().limit(3);

​        stream.forEach(System.out::println);

​        stream.close();

​    }

}

5)sorted

非终结方法 返回由此流的元素组成的流,根据自然顺序排序。

package com.aaa.newfeature.stream;

import com.aaa.newfeature.methodref.Person;

import java.util.ArrayList;

import java.util.List;

import java.util.function.BiFunction;

import java.util.stream.Stream;

/**

 \* @ fileName:StreamCreate

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/9/26 21:55

 \* @ version:1.0.0

 */

public class StreamSorted {

​    public static void main(String[] args) {

​        List<String> stringList = new ArrayList<>();

​        stringList.add("zhaoyi");

​        stringList.add("qianer");

​        stringList.add("sunsan");

​        stringList.add("lisi");

​        Stream<String> stream = stringList.stream().sorted();

​        //stream.forEach(s-> System.out.println(s));

​        stream.forEach(System.out::println);

​        stream.close();

​        System.out.println("-------------------------------------------");

​        //调用带参构造

​        //BiFunction表示接受两个参数并产生结果的函数

​        BiFunction<String,Integer, Person> personBiFunction=Person::new;

​        Person person1 = personBiFunction.apply("孙三", 10);

​        Person person2 = personBiFunction.apply("李四", 20);

​        Person person3 = personBiFunction.apply("王五", 12);

​        Person person4 = personBiFunction.apply("马六", 21);

​        List<Person> personList = new ArrayList<>();

​        personList.add(person1);

​        personList.add(person2);

​        personList.add(person3);

​        personList.add(person4);

​        personList.stream().sorted((p1,p2)->{return p1.getAge()>p2.getAge()?1:p1.getAge()<p2.getAge()?-1:0;}).forEach(System.out::println);

​    }

}

6)collect

终结方法 把一个流收集起来,最终可以是收集成一个值也可以收集成一个新的集合。collect主要依赖java.util.stream.Collectors类内置的静态方法。

因为流不存储数据,那么在流中的数据完成处理后,需要将流中的数据重新归集到新的集合里。toList、toSet和toMap比较常用,另外还有toCollection、toConcurrentMap等复杂一些的用法。

package com.aaa.jdk8nf.stream;

import com.aaa.jdk8nf.methodref.Person;

import java.util.ArrayList;

import java.util.List;

import java.util.Map;

import java.util.function.BiFunction;

import java.util.stream.Collectors;

import java.util.stream.Stream;

/**

 \* @ fileName:StreamCreate

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/10/12 17:17

 \* @ version:1.0.0

 */

public class StreamCollect {

​    public static void main(String[] args) {

​        BiFunction<String,Integer, Person> biFunction = Person::new;

​        Person person3 = biFunction.apply("王五1", 48);

​        Person person4 = biFunction.apply("王五2", 28);

​        Person person5 = biFunction.apply("王五3", 8);

​        Person person1 = biFunction.apply("王五4", 17);

​        Person person2 = biFunction.apply("王五5", 38);

​        Person person6 = biFunction.apply("李五5", 38);

​        List<Person> personList = new ArrayList<>();

​        personList.add(person3);

​        personList.add(person4);

​        personList.add(person5);

​        personList.add(person1);

​        personList.add(person2);

​        personList.add(person6);

​        Stream<Person> personStream1 = personList.stream();

​        List<Person> resultPersonList = personStream1.filter(p -> p.getAge() >= 18 && p.getName().startsWith("王"))

​                .sorted((p1, p2) -> p1.getAge() - p2.getAge()).limit(3).collect(Collectors.toList());

​        for (Person person : resultPersonList) {

​            System.out.println(person);

​        }

​        System.out.println("----------------------------------");

​        Stream<Person> personStream2 = personList.stream();

​        Map<String, Person> personMap = personStream2.filter(p -> p.getAge() >= 18 && p.getName().startsWith("王"))

​                .sorted((p1, p2) -> p1.getAge() - p2.getAge()).limit(3).collect(Collectors.toMap(Person::getName, p -> p));

​        System.out.println(personMap);

​    }

}

7)count

终结方法 统计其中的元素个数

package com.aaa.newfeature.stream;

import java.util.ArrayList;

import java.util.List;

import java.util.stream.Stream;

/**

 \* @ fileName:StreamCreate

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/9/26 21:55

 \* @ version:1.0.0

 */

public class StreamCount {

​    public static void main(String[] args) {

​        List<String> stringList = new ArrayList<>();

​        stringList.add("zhaoyi");

​        stringList.add("qianer");

​        stringList.add("sunsan");

​        stringList.add("lisi");

​        Stream<String> stream = stringList.stream();

​        //stream.forEach(s-> System.out.println(s));

​        long count = stream.count();

​        System.out.println(count);

​        stream.close();

​    }

}

8)skip

非终结方法 跳过前几个元素,可以使用 skip 方法获取一个截取之后的新流

package com.aaa.newfeature.stream;

import com.aaa.newfeature.methodref.Person;

import java.util.ArrayList;

import java.util.List;

import java.util.function.BiFunction;

import java.util.stream.Stream;

/**

 \* @ fileName:StreamCreate

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/9/26 21:55

 \* @ version:1.0.0

 */

public class StreamSkip {

​    public static void main(String[] args) {

​        //调用带参构造

​        //BiFunction表示接受两个参数并产生结果的函数

​        BiFunction<String,Integer, Person> personBiFunction=Person::new;

​        Person person1 = personBiFunction.apply("孙三", 10);

​        Person person2 = personBiFunction.apply("李四", 20);

​        Person person3 = personBiFunction.apply("王五", 12);

​        Person person4 = personBiFunction.apply("马六", 21);

​        List<Person> personList = new ArrayList<>();

​        personList.add(person1);

​        personList.add(person2);

​        personList.add(person3);

​        personList.add(person4);

​        Stream<Person> stream = personList.stream().skip(2);

​        stream.forEach(System.out::println);

​        stream.close();

​    }

}

9) find

findFirst: 从流中获取一个元素(一般情况下,是获取的开头的元素)

findAny: 从流中获取一个元素(一般情况下,是获取的开头的元素)

这两个方法,绝大部分情况下,是完全相同的,但是在多线程的环境下,findAny和find返回的结果可能不一样。

package com.aaa.newfeature.stream;

import java.util.ArrayList;

import java.util.List;

import java.util.Optional;

import java.util.stream.Stream;

/**

 \* @ fileName:StreamCreate

 \* @ description:

 \* @ author:zhz

 \* @ createTime:2022/9/26 21:55

 \* @ version:1.0.0

 */

public class StreamFind {

​    public static void main(String[] args) {

​        List<String> stringList = new ArrayList<>();

​        stringList.add("zhaoyi");

​        stringList.add("qianer");

​        stringList.add("sunsan");

​        stringList.add("lisi");

​        //stream.forEach(s-> System.out.println(s));

​        String s = stringList.stream().findFirst().get();

​        System.out.println(s);

​        Optional<String> any = stringList.stream().findAny();

​        System.out.println(any.get());

​    }

}

等等

4,知识点总结

5,本章面试题

为什么 Lambda 表达式(匿名类) 不能访问非 final 的局部变量呢?

因为实例变量存在堆中,而局部变量是在栈上分配,Lambda 表达式(匿名类) 会在另一个线程中执行。如果在线程中要直接访问一个局部变量,可能线程执行时该局部变量已经被销毁了,而 final 类型的局部变量在 Lambda 表达式(匿名类) 中其实是局部变量的一个拷贝。

​ 在java编译时,匿名内部类也会被当作普通的类处理,只不过编译器生成它构造方法的时候,除了将外部类的引用传递了过来,还将基本数据类型的变量复制了一份过来,并把引用数据类型的变量引用也传递了过来。因此,基本数据类型的变量当然不能修改了,不然就会跟外部的变量产生不一致,这样的话变量的传递也就变得毫无意义了。

标签:JDK1.8,System,特性,Person,println,import,public,out
From: https://www.cnblogs.com/zcf94264/p/17170650.html

相关文章

  • windows下载安装jdk1.8(jdk8)基础篇
    ​  一、前言目前jdk最高升级到JDK19版本了,但是大部分应用系统都是用的1.8,对于初学者来说,也需要下载安装这个版本的jdk。二、下载安装步骤一、我已经下载下来,大家到......
  • vue3的ref、reactive、toRefs特性详解
    了解ref()、reactive()这两个特性之前,我们先回顾一下vue2中data和method方法。在vue2中我们定义一个响应式变量name,通过点击事件handle来改变name的值是通过如下方式写的。......
  • 4大特性,带你认识化繁为简的华为云CodeArts Deploy
    摘要:2月27日,华为云发布持续部署服务CodeArtsDeploy,通过模块化自由编排部署流程,实现软件的自动化部署,帮助企业软件产品的快速、高效、高质量交付。本文分享自华为云社区《......
  • 语言特性
    语言特性TypeScript是一种给JavaScript添加特性的语言扩展。增加的功能包括:类型批注和编译时类型检查类型推断类型擦除接口枚举Mixin泛型编程名字空间元组A......
  • 11gR2 RAC 新特性-SCAN-GNS-RAC One Node等
    11gR2RAC新特性:1.SCAN--singleclientaccessname:客户端与RAC之前又架设了一层,目的是把RAC的IP信息对客户屏蔽掉,让用户更加方便透明......
  • ECMAScript6、7及各版本新特性,简述及深度解析
    简述:ECMAScript6(ES6)引入了更多的编程模式,包括类,模块以及for()循环。ES7 主要特性是 Array.prototype.includes(),它用于确定给定项是否在包含在数组中。ES......
  • java8新特性使用 如stream流;时间区间和模糊查询;数据源yml
    java8新特性使用如stream流,Javastream()用法集合单独取出对象中一个属性成为集合或数组java8streamuserList=userList.stream().sorted(Comparator.comparing(UserDTO:......
  • Java的特性和优点,三大版本,JDK,JRE,JVM
    Java的特性和优点面对对象跨平台性简单高性能分布式动态性多线程安全的健壮的Java的三大版本JavaSE:标准版(桌面程序,控制台开发...)JavaME:......
  • 华为云CodeArts Artifact,5大特性守护制品质量与安全
    摘要:2023年2月23日,华为云CodeArtsArtifact制品仓库服务正式上线,目标进一步赋能企业伙伴与开发者,实现软件作业中可信制品生产与应用活动快速落地,提高软件交付效率与质量。......
  • DevEco Studio 3.1 Beta1版本发布——新增六大关键特性,开发更高效
     智能代码编辑、端云一体化开发、低代码开发个性化……六大新增关键特性,开发更高效,体验更觉妙!立即点击链接下载,做DevEcoStudio3.1Beta1版本尝鲜者!下载链接:HUAWE......