jdk1.8新特性(2)

自定义函数式接口编程

我们今天再次定义一个函数式接口,加强一个函数式编程思想,直接上代码,根据代码中demo可以很好帮助我们理解函数式编程。


@FunctionalInterface
interface Functions<T,K>{
    
    
    public K get(T t1,T t2);
}

public class Function {
    
    
    public static void main(String[] args) {
    
    
        //定义4个函数
        Func<Integer,Integer> add = (a,b)->a+b;
        Func<Integer,Integer> Subtraction = (a,b)->a-b;
        Func<Integer,Integer> multi = (a,b)->a*b;
        Func<Integer,Integer> division = (a,b)->a/b;
        System.out.println("加法:"+execute(add,3,3));
        System.out.println("减法:"+execute(Subtraction,3,3));
        System.out.println("乘法:"+execute(multi,3,3));
        System.out.println("除法:"+execute(division,3,3));

    }
    public static Integer execute(Func<Integer,Integer> func,Integer s1,Integer s2){
    
    
        //对你定义的函数式逻辑执行,就是执行
        // Func<String,String> func = (a,b)->a.toUpperCase() + "-" + b.toUpperCase();
        Integer s = func.get(s1, s2);
        //可以执行你自己的业务逻辑
        //**********************************
        //返回
        return s;
    }
}

结果

加法:6
减法:0
乘法:9
除法:1

JDK8自带函数式接口

Lambda表达式必须先定义接⼝,创建相关⽅法之后才可使⽤,这样做⼗分不便,其实java8已经内置了许多接⼝, 例如下⾯四个功能型接⼝,所以⼀般很少会由⽤户去定义新的函数式接⼝
Java8的最⼤特性就是函数式接⼝,所有标注了@FunctionalInterface注解的接⼝都是函数式接⼝。

函数式接口名字 说明 方法概述
Consumer< T> 消费型接⼝:有⼊参,⽆返回值 void accept(T t);
Supplier< T> 供给型接⼝:⽆⼊参,有返回值 T get()
Function<T, R> 函数型接⼝:有⼊参,有返回值 R apply(T t)
Predicate< T> 断⾔型接⼝:有⼊参,有返回值,返回值类型确定是boolean boolean test(T t)

consumer

有入参,无返回值
常规调用

package com.example.demo.jdl8;

import org.apache.commons.lang3.StringUtils;
import java.util.function.Consumer;

public class Function2 {
    
    
    public static void main(String[] args) {
    
    
        //demo1 方法的函数调用,将入参打印出来,模拟消费了数据
        //Consumer<String> consumer = System.out::println;
        //上面例子不好理解可以这样写,跟上面逻辑一模一样
        Consumer<String> consumer = s->System.out.println(s);
        //常规调用
        consumer.accept("大步流星");
        consumer=s -> {
    
    
            String s1 = StringUtils.toRootUpperCase(s);
            System.out.println(s1);
        };
        //常规调用
        consumer.accept("jack is a good man");
        //*******************************************************************************
        //函数式调用
        System.out.println("函数式调用");
        execute(consumer,"jack is a good man");
    }
    public static <T> void execute(Consumer<T> consumer,T t){
    
    
        consumer.accept(t);
    }
}

结果

大步流星
JACK IS A GOOD MAN
函数式调用
JACK IS A GOOD MAN

集合的foreach函数参数就是消费函数

在这里插入图片描述
在这里插入图片描述

function

public class Function2 {
    
    
    public static void main(String[] args) {
    
    
        String s1 = "jack is a good man";
//        Function<String, String> toRootUpperCase = StringUtils::toRootUpperCase;
        Function<String, String> toRootUpperCase = s -> StringUtils.toRootUpperCase(s);
        System.out.println(execute(toRootUpperCase, s1));
    }
    public static <T> T execute(Function<T,T> function, T t){
    
    
        return function.apply(t);
    }
}

BiFunction传两个参数一个返回值

@FunctionalInterface
public interface BiFunction<T, U, R> {
    
    
 R apply(T t, U u);
}

demo


public class Function2 {
    
    
    public static void main(String[] args) {
    
    
        BiFunction<Integer,Integer,Integer> add = (a,b)->a+b;
        BiFunction<Integer,Integer,Integer> Subtraction = (a,b)->a-b;
        BiFunction<Integer,Integer,Integer> multi = (a,b)->a*b;
        BiFunction<Integer,Integer,Integer> division = (a,b)->a/b;
        System.out.println(execute(add,3,3));
        System.out.println(execute(Subtraction,3,3));
        System.out.println(execute(multi,3,3));
        System.out.println(execute(division,3,3));
    }
    public static <T> T execute(BiFunction<T,T,T> function, T t,T t1){
    
    
        return function.apply(t,t1);
    }
}

Supplier

提供者函数

    public static void main(String[] args) {
    
    
        Supplier<String> supplier = ()->"jack is good man";
        String execute = execute(supplier);
        System.out.println(execute);
    }
    public static <T> T execute(Supplier<T> function){
    
    
        return function.get();
    }

Predicate

断言

public class Function2 {
    
    
    public static void main(String[] args) {
    
    
        //断言型接口用于集合的过滤
        Predicate<String> predicate = a->a.length()>3;
        System.out.println(filter(predicate,Lists.newArrayList("aaaa","b","ccc","ddddd")));
    }
    public static <T> List<T> filter(Predicate<T> predicate,List<T> list) {
    
    
        List<T> results = new ArrayList<>();
        for (T str : list) {
    
    
            if (predicate.test(str)) {
    
    
                results.add(str);
            }
        }
        return results;
    }
}

方法的函数调用

我们之前调用方法都是对象名.方法名或者类名.方法名。现在如果将方法函数式调用需要使用::,返回最终是一个函数式对象。

public class Function2 {
    
    
    public static void main(String[] args) {
    
    
        System.out.println("************************构造方法demo开始*****************");
        //调用无参的构造方法,无入参无返回值
        Supplier<Clazz> loader = Clazz::new;
        Clazz clazz = loader.get();
        System.out.println("利用函数式接口无参构造方法创建的对象:"+ JSON.toJSONString(clazz));
        System.out.println("*****************************************");

        //构造函数参数不同,取决于function的引用,new方法永远有一个默认的返回值,就是这个对象
        //所以档没有参数是就是一个Supplier生产者,只有返回值没有参数
        //如果有一个参数,就是function,一个参数一个返回值,返回值永远是类对象
        Function<String, Clazz> stringClazzCacheLoader = Clazz::new;
        Clazz apply = stringClazzCacheLoader.apply("张三");
        System.out.println("利用函数式接口一个参构造方法创建的对象:"+JSON.toJSONString(apply));
        //两个参数的构造方法返回值就是bifunction,一次类推
        //如果jdk自带的函数式接口不满足要求,可以自定义函数式接口
        BiFunction<String, Integer, Clazz> bi = Clazz::new;
        Clazz clazz1 = bi.apply("张三", 22);
        System.out.println("利用函数式接口两个参构造方法创建的对象:"+JSON.toJSONString(clazz1));
        System.out.println("************************构造方法demo结束*****************");

        System.out.println("************************静态方法demo开始*****************");
        //getStatic没有参数 只有一个返回值,所有函数式接口为Supplier,一次类推
        Supplier<String> getStatic = Clazz::getStatic;
        System.out.println("函数式调用静态方法,返回值类型取决于参数与返回值:"+getStatic.get());
        System.out.println("************************静态方法demo结束*****************");

        System.out.println("************************实例方法demo开始*****************");
        //调用实例方法有两种,一种是根据实例调用 一种是根据类调用 根据类调用默认第一个参数为实例(这个是默认的 必须传值)
        //Clazz clazz2 = Clazz.class.newInstance();
        Clazz clazz2 = new Clazz("李四",22);
        //getName方法,没有入参  有返回值  生产者对象,也就是Supplier函数
        //第一种调用方方式 实例::方法名
        Supplier<String> getName = clazz2::getName;
        String name = getName.get();
        System.out.println("实例::方法名 调用:"+name);//李四
        //第二种调用方式 类型::实例方法 默认必须有一个参数 第一个参数必须为实例
        Function<Clazz, String> getName1 = Clazz::getName;
        String apply1 = getName1.apply(clazz2);
        System.out.println("类型::实例方法(默认必须有一个参数 第一个参数必须为实例) 调用:"+apply1);//李四
        System.out.println("************************实例方法demo结束*****************");
    }
}
class Clazz{
    
    

    private String name;
    private Integer age;

    public Clazz() {
    
    
    }

    public Clazz(String name) {
    
    
        this.name = name;
    }

    public static String getStatic(){
    
    
        return "空空如也";
    }

    public Clazz getObject(){
    
    
        return this;
    }

    public String getName() {
    
    
        return name;
    }

    public Clazz(String name, Integer age) {
    
    
        this.name = name;
        this.age = age;
    }

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

    public Integer getAge() {
    
    
        return age;
    }

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

结果

************************构造方法demo开始*****************
利用函数式接口无参构造方法创建的对象:{
    
    "object":{
    
    "$ref":"@"}}
*****************************************
利用函数式接口一个参构造方法创建的对象:{
    
    "name":"张三","object":{
    
    "$ref":"@"}}
利用函数式接口两个参构造方法创建的对象:{
    
    "age":22,"name":"张三","object":{
    
    "$ref":"@"}}
************************构造方法demo结束*****************
************************静态方法demo开始*****************
函数式调用静态方法,返回值类型取决于参数与返回值:空空如也
************************静态方法demo结束*****************
************************实例方法demo开始*****************
实例::方法名 调用:李四
类型::实例方法(默认必须有一个参数 第一个参数必须为实例) 调用:李四
************************实例方法demo结束*****************

集合操作Stream

如图
在这里插入图片描述
数据元素:原始集合,如List、Set、Map等
生成流:可以是串⾏流stream() 或者并⾏流 parallelStream()
中间操作:可以是 排序,聚合,过滤,转换等
终端操作,很多流操作本身就会返回⼀个流,所以多个操作可以直接连接起来,最后统⼀进⾏收集

中间操作(map、filter、sort、limit、allMatch、anyMatch、max、min、reduce等函数)并行流parallelStream

详见下面代码demo

 /*****************map函数************************/
        System.out.println("--------------map start------------------------------------");
        List<String> strings = Lists.newArrayList("1", "2", "3", "4");
        //map 函数  对集合进行置换
        //例如将某个集合中的vo对象置换为pojo对象,类似与js的map函数
        //接受的是一个function函数
        List<Integer> collect = strings.stream().map(Integer::parseInt).collect(Collectors.toList());
        //同上 List<Integer> collect = strings.stream().map(s->Integer.parseInt(s)).collect(Collectors.toList());
        System.out.println("map 转换,字符换转integer :"+collect);
        System.out.println("--------------map end------------------------------------");
        System.out.println();

        System.out.println("--------------filter start------------------------------------");
        /*****************filter函数************************/
        List<String> strings1 = Lists.newArrayList("啦啦小魔仙", "小施主", "段水流", "王","",null,"a");
        //filter 接受的是一个断言函数,返回值为boolean
        List<String> collect1 = strings1.stream().filter(StringUtils::isNoneBlank).collect(Collectors.toList());
        System.out.println("filter去空:"+collect1);
        //取到字符串长度大于3的数据
        List<String> collect2 = strings1.stream().filter(s -> StringUtils.length(s) > 3).collect(Collectors.toList());
        System.out.println("filter获取字符长度大于3:"+collect2);
        System.out.println("--------------filter start------------------------------------");
        System.out.println();

        System.out.println("--------------sort start------------------------------------");
        List<String> collect3 = collect1.stream().sorted().collect(Collectors.toList());
        System.out.println("默认自然顺序排序,类需要实现Comparable接口:"+collect3);
        //自定义排序规则 自定义Comparator,实现方法
        List<String> collect4 = collect1.stream().sorted((a, b) -> b.length() - a.length()).collect(Collectors.toList());
        System.out.println("自定义排序规则,按照长度进行排序:"+collect4);

        //传递 Comparator.comparing ,传递一个function 按照集合中对象的哪个属性排序
        List<String> collect5 = collect1.stream().sorted(Comparator.comparing(a -> a.length())).collect(Collectors.toList());
        System.out.println("自定义排序规则,按照长度进行排序:"+collect5);
        //反转排序
        List<String> collect6 = collect1.stream().sorted(Comparator.comparing(a -> a.length(), Comparator.reverseOrder())).collect(Collectors.toList());

        //String::length 方法的函数调用,返回值正好是一个function函数接口
        List<String> collect7 = collect1.stream().sorted(Comparator.comparing(String::length).reversed()).collect(Collectors.toList());
        System.out.println("自定义排序规则,按照长度进行排序(倒叙):"+collect6);
        System.out.println("自定义排序规则,按照长度进行排序(倒叙):"+collect7);

        //对集合中对象进行连续排序,先按照班级排序 再按照年龄排序
        class Study{
    
    
            Integer grade;
            Integer age;
            String name;

            public Study(Integer grade, Integer age, String name) {
    
    
                this.grade = grade;
                this.age = age;
                this.name = name;
            }

            public Integer getGrade() {
    
    
                return grade;
            }

            public void setGrade(Integer grade) {
    
    
                this.grade = grade;
            }

            public Integer getAge() {
    
    
                return age;
            }

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

            public String getName() {
    
    
                return name;
            }

            public void setName(String name) {
    
    
                this.name = name;
            }
        }
        List<Study> studies = Lists.newArrayList(
                new Study(10, 8, "周"),
                new Study(11, 9, "赵"),
                new Study(11, 7, "李"),
                new Study(10, 9, "王"),
                new Study(11, 8, "薛"));
        //先按照班级排序  再按照年龄排序  先排序字段再后面
        List<Study> collect8 = studies.stream().sorted(Comparator.comparing(a -> a.age))
                .sorted(Comparator.comparing(a -> a.grade)).collect(Collectors.toList());
        System.out.println("先按照班级排序  再按照年龄排序 :"+JSON.toJSONString(collect8));
        //先按照班级倒叙排序  再按照年龄倒叙排序
        List<Study> collect9 = studies.stream().sorted(Comparator.comparing(Study::getAge,Comparator.reverseOrder()))
                .sorted(Comparator.comparing(Study::getGrade).reversed()).collect(Collectors.toList());
        System.out.println("先按照班级倒叙排序  再按照年龄倒叙排序:"+JSON.toJSONString(collect9));
        System.out.println("--------------sort end------------------------------------");


        System.out.println("--------------limit start------------------------------------");
        List<String> list = Lists.newArrayList("java", "python", "javascript", "golang", "c++", "c");
        List<String> collect10 = list.stream().limit(1).collect(Collectors.toList());
        System.out.println("阶段流"+collect10);
        System.out.println("--------------limit end------------------------------------");

        System.out.println("--------------allMatch anyMatch start------------------------------------");
        List<String> list2 = Lists.newArrayList("java", "python", "javascript", "golang", "c++", "c");
        //allMatch 检查集合所有元素,都符合返回true
        boolean b = list2.stream().allMatch(StringUtils::isNoneBlank);
        System.out.println("集合所有元素是否都不为空:"+b);
        boolean b1 = list2.stream().allMatch(s -> s.length() > 3);
        System.out.println("集合所有元素长度是否都大于3:"+b1);
        //allMatch 检查集合所有元素,只要有一项符合返回true
        boolean b2 = list2.stream().anyMatch(s -> s.length() > 9);
        System.out.println("集合有元素长度都大于9:"+b2);

        System.out.println("--------------allMatch anyMatch end------------------------------------");

        System.out.println("--------------max min start------------------------------------");
        System.out.println("原始集合:"+studies);
//        Optional<Study> max = studies.stream().max((a, c) -> a.getGrade() - c.getGrade());
        Optional<Study> max = studies.stream().max((a, c) -> Integer.compare(a.getGrade(), c.getGrade()));
        Study study = max.isPresent() ? max.get() : null;
        System.out.println("最大班级是:"+study.getGrade());

        Optional<Study> min = studies.stream().min((a, c) -> a.getGrade() - c.getGrade());
        Study study1 = min.isPresent() ? min.get() : null;
        System.out.println("最小班级是:"+study1.getGrade());

        System.out.println("--------------max min end------------------------------------");

        System.out.println("--------------并⾏流parallelStream start------------------------------------");
//        线程池(ForkJoinPool)维护⼀个线程队列
//        可以分割任务,将⽗任务拆分成⼦任务,完全贴合分治思想
//        多数情况下并⾏⽐串⾏快
//        部分情况会有线程安全问题,parallelStream⾥⾯使⽤的外部变量
        List<String> arrayList = Lists.newArrayList("a", "b", "c", "d", "e");
        arrayList.parallelStream().forEach(System.out::println);

        System.out.println("--------------并⾏流parallelStream end------------------------------------");

        System.out.println("--------------reduce start------------------------------------");
//        根据⼀定的规则将Stream中的元素进⾏计算后返回⼀个唯⼀的值
        List<Integer> stringArrayList = Lists.newArrayList(1, 2, 3, 4, 5);
        stringArrayList.stream().forEach(System.out::println);
        Optional<Integer> reduce = stringArrayList.stream().reduce((a, c) -> a + c);
        Integer integer = reduce.isPresent() ? reduce.get() : 0;
        System.out.println("集合的合计:"+integer);
        Integer reduce1 = stringArrayList.stream().reduce(10, (a, c) -> a + c);
        System.out.println("增加初始值10集合的合计:"+reduce1);
        Optional<Integer> reduce2 = stringArrayList.stream().reduce((a, c) -> a > c ? a : c);
        System.out.println("集合的最大值:"+(reduce2.isPresent()?reduce2.get():0));

        System.out.println("--------------reduce end------------------------------------");

collector收集器

Collectors.toList()
Collectors.toMap()
Collectors.toSet()
Collectors.toCollection()
Collectors.toCollection(LinkedList::new)
Collectors.toCollection(CopyOnWriteArrayList::new)
Collectors.toCollection(TreeSet::new)

joining、partitioningBy分组、group by分组、summarizingInt(集合计算)

System.out.println("--------------collector收集器 start------------------------------------");

//        Collectors.toList()
//        Collectors.toMap()
//        Collectors.toSet()
//        Collectors.toCollection()
//            Collectors.toCollection(LinkedList::new)
//            Collectors.toCollection(CopyOnWriteArrayList::new)
//            Collectors.toCollection(TreeSet::new)

        System.out.println("--------------collector收集器 end------------------------------------");

        System.out.println("--------------joining start------------------------------------");
        List<String> arrayList1 = Lists.newArrayList("a", "b", "c", "d", "e");
        String collect11 = arrayList1.stream().collect(Collectors.joining());
        System.out.println("集合转字符串,没有任何分割符:"+collect11);
        String collect12 = arrayList1.stream().collect(Collectors.joining(","));
        System.out.println("集合转字符串,有分割符:"+collect12);
        String collect13 = arrayList1.stream().collect(Collectors.joining(",","[","]"));
        System.out.println("集合转字符串,有分割符并增加前缀与后缀:"+collect13);

        System.out.println("--------------joining end------------------------------------");

        System.out.println("--------------partitioningBy分组 group by分组 start------------------------------------");
        //partitioningBy分组  key是booleanm类型  value:此对象的集合类型
        List<Study> studyList = Lists.newArrayList(
                new Study(10, 8, "周"),
                new Study(11, 9, "赵"),
                new Study(11, 7, "李"),
                new Study(10, 9, "王"),
                new Study(11, 8, "薛"));
        //班级大于10小于10的数据
        Map<Boolean, List<Study>> listMap = studyList.stream().collect(Collectors.partitioningBy(s -> s.getGrade() > 10));
        listMap.entrySet().forEach(s->{
    
    
            System.out.println("key:"+s.getKey() + ".value:"+JSON.toJSONString(s.getValue()));
        });
        System.out.println();
        //按年龄分组
        Map<Integer, List<Study>> map = studyList.parallelStream().collect(Collectors.groupingBy(s -> s.getAge()));
        map.entrySet().forEach(s->{
    
    
            System.out.println("key:"+s.getKey() + ".value:"+JSON.toJSONString(s.getValue()));
        });
        System.out.println("--------------collector收集器 end------------------------------------");
        System.out.println();
        //分组后统计个数
//        Map<Integer, Long> collect14 = studyList.stream().collect(Collectors.groupingBy(s -> s.getAge(), Collectors.counting()));
        Map<Integer, Long> collect14 = studyList.stream().collect(Collectors.groupingBy(Study::getAge, Collectors.counting()));
        collect14.forEach((key,value)->{
    
    
            System.out.println("key:"+key + "。value:"+value);
        });

//        summarizing
        IntSummaryStatistics collect15 = studyList.stream().collect(Collectors.summarizingInt(s -> s.getAge()));
        System.out.println("平均值:" + collect15.getAverage());
        System.out.println("⼈数:" + collect15.getCount());
        System.out.println("最⼤值:" + collect15.getMax());
        System.out.println("最⼩值:" + collect15.getMin());
        System.out.println("总和:" + collect15.getSum());

        //还可以这样计算,平均年龄,summarizingInt这个函数求
        Double collect16 = studyList.stream().collect(Collectors.averagingInt(s -> s.getAge()));
//        Double collect16 = studyList.stream().collect(Collectors.averagingInt(Study::getAge));
        System.out.println("平均年龄:"+collect16);
        Integer collect17 = studyList.stream().collect(Collectors.summingInt(s -> s.getAge()));
        System.out.println("总年龄:"+collect17);

新内存空间Matespace

jdk8的修改 JDK8 HotSpot JVM 使⽤本地内存来存储类元数据信息,叫做 元空间(Metaspace)
在默认情况下Metaspace的⼤⼩只与本地内存⼤⼩有关
常⽤的两个参数 -XX:MetaspaceSize=N 指Metaspace扩容时触发FullGC的初始化阈值
-XX:MaxMetaspaceSize=N 指⽤于限制Metaspace增⻓的上限,防⽌因为某些情况导致
Metaspace⽆限的使⽤本地内存
不管两个参数如何设置,都会从20.8M开始,然后随着类加载越来越多不断扩容调整直到最⼤
查看⼤⼩ jstat -gc pid MC: current metaspace capacity MU: mateaspace utilization 单位是KB

新特性之try-with-resources

 private static void test(String filepath){
    
    
	 try(OutputStream out = new FileOutputStream(filepath);) {
    
    
		 out.write((filepath+"XXXXXXXXXXXXXXXXX").getBytes());
		 } catch (Exception e) {
    
    
		 e.printStackTrace();
	 }
 }

猜你喜欢

转载自blog.csdn.net/qq_37904966/article/details/108419228