JAVA1.8新特性

Lambda表达式:

                        为匿名内部类提供了简便的写法

                        了解内部类的使用

 public static void main1(String[] args) {
        //在方法内部定义内部类
        class MyClass{
            public void say(){
                System.out.printf("我是内部类");
            }
        }
        //使用内部类创建对象
        MyClass myClass = new MyClass();
        myClass.say();
        //简便写法
        new MyClass().say();
}

优化成匿名内部类

public interface MyInferface1 {
    void run();
}

在代码中使用创建对象

public static void main2(String[] args) {
        //匿名内部类
        //匿名内部类,必须继承其他类或者是实现某个接口
        MyInferface1 myInferface1 = new MyInferface1() {
            @Override
            public void run() {
                System.out.println("我是匿名内部类");
            }
        };
        myInferface1.run();
        /省略引用
        new MyInferface1(){

            @Override
            public void run() {
                System.out.println("我是匿名内部类2");
            }
        }.run();
    }

lambda表达式的优化

         必须是接口,而且只能有一个抽象方法

                

public interface MyInterface{

    void run();
}

必须通过引用接收创建对象

 public static void main3(String[] args) {
        //lambda表达式对匿名内部类的优化
        //1,必须是接口
        //2, 只能有一个未实现的方法
        MyInferface1 myInferface1 = ()->{
            System.out.println("lambda表达式");
        };
        myInferface1.run();
    }

  主要是把接口当参数传递到别的方法中(用来模拟函数的引用传递)

        定义接口

public interface MyForEachInterface {
    void each(Object o);
}

        定义调用方法

    //实现了一个方法,可以遍历集合
    public static void myForEach(List list,
                                 MyForEachInterface eachInterface){
        for(int i=0;i<list.size();i++){
            //调用了传递进入来的接口的方法
            eachInterface.each(list.get(i));
        }
    }

        使用这个myForEach方法的时候,通过lambda表达式传递方法的引用

 public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        for (int i=0;i<10;i++){
            list.add(i);
        }
        //使用lambda表达式遍历
        list.forEach(obj->{
            System.out.println("打印方式1"+obj);
        });

        myForEach(list,obj->{
            System.out.println("打印方式2"+obj.toString());
        });
    }

函数接口:

                在java中不能将方法作为参数传递到别的方法中,但是C或者是js都是可以的

                在java中把只有一个方法的接口叫做函数接口,然后在利用lambda表达式,让接口的传递看起来像函数传递

                为保证函数接口的规范,jdk1.8推出了一些规则

                        在接口上使用@FunctionalInterface,检查这个接口是不是函数接口

@FunctionalInterface
public interface MyInterface2 {
    void accept();
}

为了方便使用jdk1.8自带了一些接口

        Consumer<T>:定义一个抽象方法可以传值,但没有返回,消费接口

        Supplier<T>:有返回没参数,只有返回结果,提供接口

        Function<T,R>:有参数有返回结果,功能接口

        Predicate<T>:可以传入参数,返回类型是boolean类型,断言接口

方法引用:

        在lambda表达式基础上进一步简化                

        //使用lambda表达式输出
        list.forEach(integer -> {
            System.out.println(integer);
        });
        //使用方法引用进一步简化
        list.forEach(System.out::println);

        可以使用方法引用的条件      

                lambda表达式中只有一行代码

                调用方法,和lambda传入的接口的方法的参数和返回保持一致

         常用的简化形式

                类::静态方法:一般用于静态方法

                对象::实例方法:一般用于对象直接调用方法(传入的对象,被作为参数被省略的方法引用作为参数调用) 

        //使用lambda表达式输出
        list.forEach(integer -> {
            System.out.println(integer);
        });
        //使用方法引用进一步简化
        list.forEach(System.out::println);

        类::实例方法,这个实例方法是通过调用类代替对象调用的(调用传入对象的方法).  

                在类实现一个非static方法 

    public void say(){
        System.out.println("我是"+this.getName()+",今年"+this.getAge());
    }

      在使用lambda表达式的时候使用传入的参数对象,调用say()方法

 list.forEach(s->{
            s.say();
  });

        在省略参数的时候,由于没有可以调用方法的媒介,可以直接使用类进行调用

list.forEach(Student::say);

        类::new  对象

                当返回结果是一个对象的时候,并且函数体时创建对象,那么可以使用方法引用省略

                在调用的时候,构造返回的参数要和接口应用的参数保持一致

  public static void main(String[] args) {
        //匿名内部类的写法
        wrap(new Supplier<String>() {
            @Override
            public String get() {
                return new String();
            }
        });
        //lambda表达式
        wrap(()->{
            return new String();
        });
        //进一步简化
        wrap(()-> new String());

        //使用引用简化
        wrap(String::new);
    }

    public static void wrap(Supplier<String> supplier){
        System.out.println("包装开始");
        String result = supplier.get();
        System.out.println("获取包装结果");

    }

简化小结:

        匿名内部类:

        wrap("12", new Function<String, Object>() {
            @Override
            public Object apply(String s) {
                return new Short(s);
            }
        });

        匿名内部类,在实现接口的情况下,并且接口之后只有一个方法,那么就可以简化成lambda表达式

 wrap("15", s -> {
            return new Integer(s);
});

lambda表达式中,如果之后一行代码,那么{}可以省略,如果带返回值的话那么return也会省略

 wrap("15", s -> new Integer(

如果调用一行代码,参数和返回与接口的抽象方法,保持一致,那么则可以使用方法引用

wrap("15",Integer::new);

Stream 

        流可以对集合进行筛选,快速获得想要的结果

                如果没有流要么遍历多次,要么就要别的集合来进行辅助操作

  public static void main2(String[] args) {
        List<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
        // 需求:1.拿到所有姓张的 2.拿到名字长度为3个字的 3.打印这些数据

        //获取所有姓张的
        List<String> nameList  = new ArrayList<>();
        for (int i=0;i<list.size();i++){
            String name = list.get(i);
            if(name.contains("张")){
                nameList.add(name);
            }
        }

        //在原有的基础上再次进行遍历
        List<String> lengthList  = new ArrayList<>();
        for (int i=0;i<nameList.size();i++){
            String name = nameList.get(i);
            if(name.length()==3){
                lengthList.add(name);
            }
        }

        //将结果打印
        for (int i=0;i<lengthList.size();i++){
            String name = lengthList.get(i);
            System.out.println(name);
        }
    }

使用流简化操作

  public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
        // 需求:1.拿到所有姓张的 2.拿到名字长度为3个字的 3.打印这些数据
        //获取流
        Stream<String> stream = list.stream();
        //过滤获取所有姓名张的
        /*
        stream
                .filter(new Predicate<String>() {//过滤方法
            @Override
            public boolean test(String o) {
                if(o.contains("张")){
                    return true;
                }
                return false;
            }
        }).filter(new Predicate<String>() {//筛选
            @Override
            public boolean test(String s) {
                if(s.length()==3){
                    return true;
                }
                return false;
            }
        }) .forEach(s->{//终结遍历方法
            System.out.println(s);
        });*/
        //过滤方法
        //筛选
        stream
                .filter(o -> o.contains("张"))
                .filter(s ->s.length()==3)
                .forEach(System.out::println
        );

    }

流的特点:

                Stream自己不会储存元素

                Stream不会改变源对象.相反,它们会返回一个有结果的新Steam

                Stream是延迟执行,会等到需要结果的时候执行

流的基本使用;

                通过Collection对象的Stream()或parallelStream()方法

                通过ArrayList类的stream()方法

                通过Stream接口的of(),iterate(),generate()方法

      //自动无限生产数据
        Stream s2 = Stream.generate(new Supplier<Integer>() {
            @Override
            public Integer get() {
                return new Random().nextInt(100);
            }
        });
        s2.limit(5) //只获取5个数据
                .forEach(i->{
            System.out.println(i);
        });

        通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法。

流的中间操作方法

             filter:过滤器操作

             limit:限制只有几个

             skip:跳过元素

             distinct:去掉重复,对象的话要重写equals方法

             sorted:排序

    s2.limit(10)
                .sorted((o1, o2) -> o2-o1)
                .forEach(i->{
            System.out.println(i);
        });

  流的终极操作

                foreach:循环

                max:最大值

                reduce:可以根据自定义规则计算数据

                collect:将筛选出来的结果保存在新集合中

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值