Lambda表达式,Stream流,方法引用,Base64(JDK8新特性)

17 篇文章 0 订阅
5 篇文章 0 订阅

Labda表达式

Lambda表达式演示

  1. Lanbda表达式:是JDK1.8提出的一种新语法。是对之前的某种情况的代码的“简化写法”。
  2. Lambda表达式演示:
public class Demo01 {
    public static void main(String[] args) {
        //1.之前我们实现一个线程——可以使用"匿名内部类"的形式:new Thread(Runnable的匿名内部类).start()
        /*new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 30; i++) {
                    System.out.println("敌人开枪:" + i);
                }
            }
        }).start();*/

        //2.这种情况就可以使用Lambda
        new Thread(()-> {
                for (int i = 0; i < 30; i++) {
                    System.out.println("敌人开枪:" + i);
                }
        }).start();

        for (int i = 0; i < 30; i++) {
            System.out.println("我开枪:" + i);

        }
    }
}

Lambda的使用前提及函数式接口的概念

  1. Lambda的使用前提:
    1. 当我们面向的是一个接口时,例如:new Thread(Runnale接口).start()
    2. 接口中有且仅有一个需要子类必须实现的抽象方法。例如:Runnable接口中的run()方法。
  2. 函数式接口的概念:
    接口中有且仅有一个需要子类必须实现的抽象方法,这种接口就叫:函数式接口
    只有使用函数式接口的地方,才可以使用Lambda表达式
  3. @FunctionaInterface注解:
//我们可以自己定义函数式接口

@FunctionalInterface//此注解可以保证下面定义的接口一定是一个标准的"函数式接口"
interface IAnimal{
    public abstract void show();

    public default void show1(){
    }
    public static void show2(){
    }

    public abstract String toString();//OK,可以定义和Object签名相同的抽象方法,这种方法子类会从Object继承,所以不用必须重写
    public abstract boolean equals(Object obj);//OK的。
//    public abstract String aString();//错误
}
class Cat implements IAnimal{
    @Override
    public void show() {
        System.out.println("小猫喵喵...");
    }
}
public class Demo02 {
    public static void main(String[] args) {
        //1.调用fun()——传入"子类对象"
        fun(new Cat());
        //2.调用fun()——传入"匿名内部类对象"
        fun(new IAnimal() {
            @Override
            public void show() {
                System.out.println("小狗汪汪...");
            }
        });
        //3.调用fun()——传入"Lambda表达式"
        fun(()->{
            System.out.println("小猪哼哼...");
        });
    }
    public static void fun(IAnimal a){
        a.show();
    }
}

函数式编程思想

  1. 面向对象的编程思想:必须要定义类、创建对象、传入对象
  2. 函数式编程思想:不用定义类、不用创建对象,只传入“方法(函数)”。
  3. 好处:
    1. 简化了写法;
    2. 提高了效率(不用创建对象)
@FunctionalInterface//此注解可以保证下面定义的接口一定是一个标准的"函数式接口"
interface IAnimal{
    public abstract void show();
}

public class Demo02 {
    public static void main(String[] args) {
        //3.调用fun()——传入"Lambda表达式"
        fun(()->{//Lambda表达式:其实就是一个“方法(函数)”——这被称为:函数式编程思想,打破了之前面向对象的编程方式
            System.out.println("小猪哼哼...");
        });
    }
    public static void fun(IAnimal a){//IAnimal就是一个“函数式接口”类型
        a.show();
    }
}

Lambda的标准格式:

  1. Lambda的标准格式:
    1. 一对小括号:(就是形参)
    2. 一个右箭头:->
    3. 一对大括号:{方法体}
  2. 抽象方法是无参无返回值的情况:指函数式接口中的抽象方法是“无参,无返回值”的,那么Lambda就是无参无返回值的。
new Thread(()->{
				for(int i = 0;i < 30 ; i++){
					System.out.println(“敌人开枪:” + i);
				}
			).start();

  1. 抽象方法是有参有返回值的情况:指函数式接口中的抽象方法是有参有返回值的,那么Lambda就是有参有返回值的。
	public class Demo03 {
    public static void main(String[] args) {
        List<Integer> intList = new ArrayList<>();
        intList.add(10);
        intList.add(59);
        intList.add(22);
        intList.add(55);
        intList.add(88);
        intList.add(17);

        //对集合元素进行"降序"排序,怎么排??????
        /*Collections.sort(intList, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });*/

        //我们发现:Comparator就是一个"函数式接口",就意味着可以使用:Lambda表达式
        Collections.sort(intList,(Integer o1 ,Integer o2)->{ return o2 - o1;});

        System.out.println(intList);
    }
}

Lambda的省略格式

  1. Lambda的省略格式:
    1. 形参有关:形参的数据类型都可以省略。无论有几个参数。

    2. 形参有关:如果形参只有一个,可以同时省略:数据类型,一对小括号
      如果省略小括号,必须省略数据类型
      如果省略数据类型,可以不省略小括号

    3. 方法体有关:如果方法体只有一句话,可以同时省略:一对大括号,语句后的分号,return关键字(如果有)。三个部分:要省则全部省略,要用则全部使用

代码演示:
//1.自定义一个函数式接口
@FunctionalInterface
interface IAnimal{
    public String eat(String s);
}
class Cat implements IAnimal{
    @Override
    public String eat(String s) {
        System.out.println("小猫吃:" + s);
        return "小猫";
    }
}
public class Demo04 {
    public static void main(String[] args) {
        //1.传入子类对象
        fun(new Cat(),"猫粮");

        //2.传入匿名子类对象
        fun(new IAnimal() {
            @Override
            public String eat(String s) {
                System.out.println("小狗吃:" + s);
                return "小狗";
            }
        },"骨头");

        //3.传入Lambda表达式--完整格式
        fun((String s)->{
            System.out.println("小猪吃:" + s);
            return "小猪";
        },"白菜");

        //4.传入Lambda表达式--省略格式
        //假如:Lambda的方法体中,只有一句:return "小鸡";
        fun(x -> "小鸡" , "小米");

        //练习:
        List<Integer> intList = new ArrayList<>();
        intList.add(10);
        intList.add(59);
        intList.add(22);
        intList.add(55);
        intList.add(88);
        intList.add(17);

        Collections.sort(intList, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });

        //使用省略格式
        Collections.sort(intList,(i1,i2)-> i2 - i1);

    }
    public static void fun(IAnimal a,String s){
        String eat = a.eat(s);
        System.out.println(eat);
    }
}

Lambda的几种使用形式:

  1. 方法的实参使用Lambda:
new Thread(()->{
				for(int i = 0;i < 30 ; i++){
					System.out.println(“敌人开枪:” + i);
				}
			}).start();

  1. 使用变量的方法:函数式接口 变量名 = Lambda表达式;
	Runnable r = ()->{
				for(int i = 0;i < 30 ; i++){
					System.out.println(“敌人开枪:” + i);
				}
			};
		new Thread(r).start();

  1. 方法的返回值使用Lambda:
public static void main(String[] args){
				Runnable r = getRun();//Runnable r = Lambda表达式;
				new Thread(r).start();
			}
			public static Runnable(函数式接口类型) getRun(){
				return ()->{
				for(int i = 0;i < 30 ; i++){
					System.out.println(“敌人开枪:” + i);
				}
						};
			}

Stream流

  1. JDK8提出了”Lambda表达式“,同时也提供了一个”Lambda表达式“的应用–Stream流。Stream流类似于”迭代器“,但它比迭代器更强大,它可以结合Lambda对大量的数据进行反复的:筛选,过滤,汇总等操作,用起来比较方便。
	public class Demo05 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("章子怡");
        list.add("张无忌");
        list.add("张三丰");
        list.add("刘德华");
        list.add("成龙");
        list.add("张三");

        //需求:请筛选中集合中所有的"张姓"学员,而且筛选后,只打印"前两名"
        List<String> zhangList = new ArrayList<>();
        //遍历原集合
        for (String s : list) {
            if (s.startsWith("张")) {
                zhangList.add(s);
            }
        }
        //只打印前两名
        for (int i = 0; i < 2; i++) {
            System.out.println(zhangList.get(i));

        }
        System.out.println("----------------------------------------------------");
        //使用Stream流 + Lambda表达式
        list.stream().filter(s -> s.startsWith("张"))//筛选张姓学员
                .limit(2)//保留前两个
                .forEach(s -> System.out.println(s));//打印每一个

    }
}

Stream流:获取流的方式

  1. 通过Collection集合获取流:Collection接口中的”默认方法:Stream()“可以获取流:
List<String> list = new ArrayList<>();
			...
			Stream<String> stream = list.stream();
			------------------------------------------------------------------
			Set<String> set = new HashSet<>();
			...
			Stream<String> setStream = set.stream();
  1. 通过Map集合获取流:Map不能直接获取流,只能获取“键,键值对”的Set集合,然后再获取Set集合的Stream流。
	Map<Integer,String> map = new HashMap<>();
	map.put(....);
	//1.获取键的流
	Stream<Integer> keyStream = map.keySet().stream();
	//2.获取键值对的流
	Stream<Map.Entry<Integer,String>> entryStream = map.entrySet().stream();
	//3.获取值的流
	Stream<String> valueStream = map.values().stream();
  1. 通过引用类型数组获取流:
Integer[] arr = {10,20,30,40,50};
			Stream<Integer> intStream = Stream.<Integer>of(arr);//只能获取“引用类型数组”的流。

  1. 通过基本类型数组获取流:
int[] arr = {1,2,3,4,5};
			IntStream intStream = IntStream.of(arr);

  1. 通过一些零散的数据获取流:
Stream<String> strStream = Stream.<String>of(”张三”, ”李四”, ”张三丰”, ”章子怡”);

流式思想及惰性求值

  1. 在流的方法中,有些方法调用后,程序没有任何打印,这是因为Stream流中采用了:流式操作,惰性求值。
  2. 流式操作:就类似于流水线,一个节点,一个节点的。下一个节点的工作内容是由上一个节点提供的。
  3. 惰性求值:
    1. 拼接方法:此方法会返回一个Stream流,例如:filter
    2. 终结方法:此方法不是返回一个Stream流,例如:forEach
  4. Stream流的工作方式:当我们调用Stream流的“拼接方法”时,方法内部指挥记录,不工作。而我们调用Stream流的“终结方法”时,这时才让之前所有节点开始工作—这种工作方式叫:惰性求值。
  5. 一个Stream流,只能用一次。
代码演示:
public class Demo08 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("章子怡");
        list.add("张无忌");
        list.add("张三丰");
        list.add("刘德华");
        list.add("成龙");
        list.add("张三");
        list.add("李四");

        /*Stream<String> stream1 = list.stream();
        //筛选张姓
        Stream<String> stream2 = stream1.filter(s -> s.startsWith("张"));
        //筛选三个字的
        Stream<String> stream3 = stream2.filter(s -> s.length() == 3);
        //打印最终结果
        stream3.forEach(s -> System.out.println(s));*/
        //写成一句话
        list.stream().filter(s -> s.startsWith("张"))
                .filter(s -> s.length() == 3)
                .forEach(s -> System.out.println(s));
    }
}

Stream流的常用方法:

forEach()逐一处理

forEach()方法的作用:“终结方法”。它内部会循环遍历每个元素,并且调用我们的Lambda表达式,并且将每个元素作为参数传给Lambda表达式。

代码演示:
public class Demo06 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("章子怡");
        list.add("张无忌");
        list.add("张三丰");
        list.add("刘德华");
        list.add("成龙");
        list.add("张三");
        list.add("李四");

        //1.获取流
        Stream<String> stream = list.stream();
        //2.操作流:forEach()
        /*stream.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });*/
        //3.使用Lambda-完整格式
        /*stream.forEach((String s)->{
            System.out.println(s);
        });*/

        //4.使用Lambda-省略格式
        stream.forEach(s -> System.out.println(s));

        System.out.println("=================================================");
        //练习
        //要求:将上述集合中的所有元素存储到一个新集合中
        List<String> newList = new ArrayList<>();
        list.stream().forEach(s -> newList.add(s));
        System.out.println(newList);
    }
}

filter()方法:过滤

filter方法的作用:“拼接方法”。它内部也会遍历每个元素,在遍历时会将每个元素传入到我们的Lambda表达式中,根据表达式的返回结果。
true:会将此元素包含在新流中(可以这样认为)。
false:就会略过此元素。

代码演示:
public class Demo07 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("章子怡");
        list.add("张无忌");
        list.add("张三丰");
        list.add("刘德华");
        list.add("成龙");
        list.add("张三");
        list.add("李四");

        //筛选出所有的张姓学员
        /*Stream<String> stream1 = list.stream();
        Stream<String> stream2 = stream1.filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                return s.startsWith("张");
            }
        });
        stream2.forEach(s -> System.out.println(s));*/

        //改成Lambda--省略格式
        list.stream().filter(s -> s.startsWith("张"))
                .forEach(s -> System.out.println(s));
    }
}

count()方法:统计个数

count方法的作用:”终结方法“,统计筛选的元素数量。

代码演示:
public class Demo09 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("章子怡");
        list.add("张无忌");
        list.add("张三丰");
        list.add("刘德华");
        list.add("成龙");
        list.add("张三");
        list.add("李四");

        //统计张姓学员的数量
        long count = list.stream().filter(s -> s.startsWith("张"))
                .count();
        System.out.println("张姓学员共有:" + count);
    }
}

limit()方法:取前几个元素

limit()方法的作用:”拼接方法“,取筛选的前几个元素。

代码演示:
public class Demo10 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("章子怡");
        list.add("张无忌");
        list.add("张三丰");
        list.add("刘德华");
        list.add("成龙");
        list.add("张三");
        list.add("李四");

        //筛选出所有的"张姓"学员,取前2名
        list.stream().filter(s -> s.startsWith("张"))
                .limit(2)
                .forEach(s -> System.out.println(s));
    }
}

skip()方法:跳过前几个元素

slip()方法的作用:”拼接方法“跳过前几个元素。

代码演示:
	public class Demo11 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("章子怡");
        list.add("张无忌");
        list.add("张三丰");
        list.add("刘德华");
        list.add("成龙");
        list.add("张三");
        list.add("李四");

        //筛选所有张姓学员,跳过前2个
        list.stream().filter(s -> s.startsWith("张"))
                .skip(2)
                .forEach(s -> System.out.println(s));
    }
}

map()方法:转型

  1. map()方法的作用:”拼接方法“可以将一种泛型的流转换为另外一种泛型的流。
代码演示:将Stream 转换为Stream流。
public class Demo12 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("10");
        list.add("20");
        list.add("30");
        list.add("40");
        list.add("50");
        list.add("60");
        list.add("70");

        //将list中每个元素 + 5 ,然后打印
        /*list.stream().map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return Integer.valueOf(s);
            }
        }).forEach(n -> System.out.println(n + 5));*/

        //使用Lambda
        list.stream().map(s -> Integer.valueOf(s))
                .forEach(n -> System.out.println(n + 5));

        System.out.println("==================================================");
        List<String> strList = new ArrayList<>();
        strList.add("黄渤");
        strList.add("黄晓明");
        strList.add("黄磊");
        strList.add("黄老邪");

        //需求:将集合中每个人名构造一个Student对象,并打印这个对象
        /*strList.stream().map(new Function<String, Student>() {
            @Override
            public Student apply(String s) {
                return new Student(s);
            }
        }).forEach(student -> System.out.println(student));*/

        //改成Lambda
        strList.stream().map(s -> new Student(s))
                .forEach(student -> System.out.println(student));
    }
}

concat()方法:组合

Stream流的静态方法:concat()作用:将两个流合并为一个流。

代码演示
	public class Demo13 {
    public static void main(String[] args) {
        List<String> list1 = new ArrayList<>();
        list1.add("黄磊");
        list1.add("黄渤");
        list1.add("黄老邪");

        List<String> list2 = new ArrayList<>();
        list2.add("黄奕");
        list2.add("杨幂");
        list2.add("迪丽热巴");

        //将两个集合中的所有元素全部打印
        Stream.concat(list1.stream(),list2.stream())
                .forEach(s -> System.out.println(s));
    }
}

综合案例:

/*
1. 第一个队伍只要名字为3个字的成员姓名;filter()
2. 第一个队伍筛选之后只要前3个人;limit()

        3. 第二个队伍只要姓张的成员姓名;filter()
        4. 第二个队伍筛选之后不要前2个人;slip()

        5. 将两个队伍合并为一个队伍;concat()
        6. 根据姓名创建 Person 对象;map()
        7. 打印整个队伍的Person对象信息。forEach()
     */
	public class Demo14 {
    public static void main(String[] args) {
        List<String> one = new ArrayList<>();
        one.add("迪丽热巴");
        one.add("宋远桥");
        one.add("苏星河");
        one.add("老子");
        one.add("庄子");
        one.add("孙子");
        one.add("洪七公");

        List<String> two = new ArrayList<>();
        two.add("古力娜扎");
        two.add("张无忌");
        two.add("张三丰");
        two.add("赵丽颖");
        two.add("张二狗");
        two.add("张天爱");
        two.add("张三");

        /*
            1. 第一个队伍只要名字为3个字的成员姓名;filter()
            2. 第一个队伍筛选之后只要前3个人;limit()

            3. 第二个队伍只要姓张的成员姓名;filter()
            4. 第二个队伍筛选之后不要前2个人;slip()

            5. 将两个队伍合并为一个队伍;concat()
            6. 根据姓名创建 Person 对象;map()
            7. 打印整个队伍的Person对象信息。forEach()
         */

        Stream.concat(one.stream().filter(s -> s.length() == 3).limit(3),
                      two.stream().filter(s -> s.startsWith("张"))
                              .skip(2))
                              .map(s -> new Person(s))
                              .forEach(person -> System.out.println(person));

    }
}

函数拼接与终结方法

函数的拼接与终结方法

Stream流的结果收集到集合和数组中

我们之前的操作结果都是通过forEach()方法打印了。如果我们想将筛选的结果存储到一个新集合,可以通过Stream的一些方法,将筛选的结果转换为集合,数组。

	public class Demo15 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("章子怡");
        list.add("张无忌");
        list.add("张三丰");
        list.add("刘德华");
        list.add("成龙");
        list.add("张三");
        list.add("李四");

        //筛选出所有的张姓学员,存储到一个新集合
        List<String> zhangList = list.stream().filter(s -> s.startsWith("张"))
                .collect(Collectors.toList());
        System.out.println(zhangList);
        System.out.println("======================================");
        Set<String> zhagnSet = list.stream().filter(s -> s.startsWith("张"))
                .collect(Collectors.toSet());
        System.out.println(zhagnSet);
        System.out.println("======================================");
        //提取出数组
        Object[] objs = list.stream().filter(s -> s.startsWith("张"))
                .toArray();
        System.out.println(Arrays.toString(objs));
    }
}

Lambda方法的引用

方法引用概述:

  1. “方法引用”指在我们编写Lambda时,如果已有的某个类中的某个方法已经做了一样的事情,这时就可以省略Lambda表达式,直接引用现有的方法即可
  2. 方法引用的形式:
    1. 通过“对象名”引用“普通成员方法”;
    2. 通过“类名”引用“静态成员方法”;
    3. 引用某个类的某个“构造方法”;
    4. 通过“类名”引用“普通成员方法”【比较特殊,有一定的前提条件】

普通成员方法引用

  1. 普通成员方法引用:指通过“对象名”引用“它的某个普通成员方法”
  2. 格式为:
    对象名::普通成员方法(注意没有小括号)
    使用“方法引用”的前提:必须要能够使用Lambda
代码演示:

测试类

package com.itheima.demo03_Lambda方法引用_普通成员方法引用;

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

public class Demo03 {
    public static void main(String[] args) {
        //1.制作一个线程,里面模拟敌人开30枪
        //使用匿名内部类
        /*new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 30 ; i++) {
                    System.out.println("敌人开枪 " + i);
                }
            }
        }).start();*/

        //使用Lambda
        /*new Thread(()->{
            for (int i = 0; i < 30; i++) {
                System.out.println("敌人开枪:" + i);
            }
        }).start();*/

        //这时,我们发现Student类中的show()方法的功能跟我们Lambda的功能是一样的,而且show()方法形参、返回值也和Lambda一样的,这时,我们就可以引用Student类的show(),不用写Lambda表达式了。
        //引用show是普通成员方法,必须先创建对象
        Student stu = new Student();
        new Thread(stu::show).start();


        //主线程继续向下
        for (int i = 0; i < 30; i++) {
            System.out.println("我开枪:" + i);
        }

        System.out.println("====================================");
        //练习:
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("张三丰");
        list.add("章子怡");
        list.add("张学友");

        //使用Stream流打印每个元素
        //匿名内部类
        /*list.stream().forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });*/
        //使用Lambda
//        list.stream().forEach(s -> System.out.println(s));

        //Lambda整体的功能:接收一个字符串,打印一个字符串
        //大家想一想:有没有哪个类的哪个方法也是一样的功能:接收一个字符串,打印一个字符串???????????
        //System.out(PrintStream类)里面的一个println(String s):接收一个字符串,向控制台打印一个字符串
        //所以:我们Lambda这里就可以引用println(String s)方法
        /*PrintStream ps = System.out;
        list.stream().forEach(ps::println);*/

        //简写
        list.stream().forEach(System.out::println);


    }
}

Student类

package com.itheima.demo03_Lambda方法引用_普通成员方法引用;

public class Student {
    public void show(){
        for (int i = 0; i < 30; i++) {
            System.out.println("student敌人开枪:" + i);
        }
    }

    public void show1(){

    }
}
代码图解:

在这里插入图片描述

静态成员方法引用

  1. 指:通过“类名”引用它的某个“静态成员方法”;
  2. 格式:
    类名::静态方法名(没有小括号)
代码演示:
package com.itheima.demo04_Lambda方法引用_静态成员方法引用;

//1.自定义一个函数式接口
interface ICalc{
    public int getMax(int a, int b);
}
public class Demo04 {
    public static void main(String[] args) {
        //1.匿名内部类
        /*fun(new ICalc() {
            @Override
            public int getMax(int a, int b) {
                return a > b ? a : b;
            }
        },10,20);*/

        //2.使用Lambda
//        fun((a, b) -> a > b ? a : b, 100, 200);

        //3.Lambda整体功能:接收两个int值,并求出一个最大的,然后返回
        //想一想:有没有哪个类的,哪个方法跟Lambda的功能是一样的?????????
        //Math类中有一个max(int a,int b)就是做一样的事情,而且参数、返回值都一样
        //所以:可以省略Lambda,引用Math类的静态方法:max(int a,int b)
        fun(Math::max, 1000, 2000);
    }

    //2.定义一个方法,形参是这个函数式接口类型
    public static void fun(ICalc calc, int x, int y) {//fun(ICalc)相当于:Thread(Runnable r)构造方法,都是方法,而且都接收一个:函数式接口,为了后面使用Lambda和方法引用
        int max = calc.getMax(x, y);
        System.out.println("max = " + max);
    }
}

代码图解

在这里插入图片描述

构造器引用

代码演示:

测试类

package com.itheima.demo05_Lambda方法引用_构造器引用;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;

public class Demo05 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();

        list.add("章子怡");
        list.add("杨幂");
        list.add("迪丽热巴");
        list.add("古力娜扎");

        //使用stream流将这些人名封装成Person对象,并打印这些对象
        //使用匿名内部类
       /* list.stream().map(new Function<String, Person>() {
            @Override
            public Person apply(String s) {
                return new Person(s);
            }
        }).forEach(person -> System.out.println(person));*/

        //使用Lambda
        /*list.stream().map(s -> new Person(s))
                    .forEach(System.out::println);*/

        //Person类的带参的构造方法,也是接收一个String,而且也可以创建一个Person对象
        //所以:map()中就可以引用:Person(String s)构造方法
        list.stream().map(Person::new)
                .forEach(System.out::println);

    }
}

Person类

package com.itheima.demo05_Lambda方法引用_构造器引用;

public class Person {
    private String name;

    public Person() {
    }

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

    public String getName() {
        return name;
    }

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

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}
代码图解

在这里插入图片描述

类的成员方法引用

指通过“类名”引用“普通成员方法”【有一定的使用前提】

代码演示:
package com.itheima.demo06_Lambda方法引用_类的成员方法引用;

//1.定义一个函数式接口
interface IA{
    //在第一参数中查找第二个参数的出现位置
    public int findStr(String src,String subStr);
}
public class Demo06 {
    public static void main(String[] args) {
        //1.使用匿名内部类的形式
        fun(new IA() {
            @Override
            public int findStr(String src, String subStr) {
                return src.indexOf(subStr);
            }
        }, "我爱Java", "Java");

        //2.使用Lambda
        //fun((a, b) -> a.indexOf(b), "我爱Java", "Java");

        //3.Lambda的方法体中:调用了第一个参数(String类型)的indexOf(第二个参数(String类型))这种新式
        //这时就可以直接引用:第一个参数(String类型)的indexOf()方法
        //通过"类名"引用"普通成员方法"
        //fun(String::indexOf, "我爱Java", "Java");
    }

    //2.写一个方法,形参是函数式接口:IA
    public static void fun(IA a,String src,String subStr){


        int index = a.findStr(src, subStr);//自动调用:int index = src.indexOf(subStr)


        System.out.println(subStr + " 在 " + src + " 中出现的位置:" + index);
    }
}
代码图解

在这里插入图片描述

Base64

Base64概述

  1. Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法
  2. 在Java 8 中,Base64编码已经成为Java类库的标准,Java6内置了Base64编码的编码器和解码器。
  3. Base64工具类提供了一套静态方法获取下面三种Base64编解码器
    1. 基础:输出被映射到一组字符A-Za-z0-9+/,编码不添加任何行标,输出的解码仅支持A-Za-z0-9+/.
    2. URL:输出映射到一组字符A-Za-z0-9+_,输出是URL和文件。
    3. MIME:输出映射到MIME友好格式。输出每行不超过76字符,并且使用‘\r’并跟随“\n”作为分割。编码输出最后没有行分割
  4. Base64了欸的很多方法都是从java.lang.Object类继承

常用方法:

  1. public String encodeToString​(byte[] src)//使用Base64编码方案将指定的字节数组编码为字符串。
  2. public byte[] decode​(String src)//使用Base64编码方案将Base64编码的字符串解码为新分配的字节数组。
  3. public static Base64.Encoder getEncoder​()//返回一个Base64.Encoder ,它使用Basic类型base64编码方案进行编码。
  4. public static Base64.Decoder getDecoder​()//返回Base64.Decoder解码使用Basic型base64编码方案。
代码演示:
package com.itheima.demo07_Base64加密解密演示;

import java.util.Base64;

import static java.lang.Integer.decode;

public class Demo07 {
    public static void main(String[] args) {
        String str = "这是一个明文字符串";
        String url = "http://localhost:8080/itcast/index?username=张三&pwd=1111";


        //编码(加密)
        Base64.Encoder ec = Base64.getEncoder();
        String s1 = ec.encodeToString(str.getBytes());//6L+Z5piv5LiA5Liq5piO5paH5a2X56ym5Liy
        String s2 = ec.encodeToString(url.getBytes());//aHR0cDovL2xvY2FsaG9zdDo4MDgwL2l0Y2FzdC9pbmRleD91c2VybmFtZT3lvKDkuIkmcHdkPTExMTE=

        System.out.println("加密:");
        System.out.println(s1);//6L+Z5piv5LiA5Liq5piO5paH5a2X56ym5Liy
        System.out.println(s2);//aHR0cDovL2xvY2FsaG9zdDo4MDgwL2l0Y2FzdC9pbmRleD91c2VybmFtZT3lvKDkuIkmcHdkPTExMTE=


        System.out.println("传输......");

        System.out.println("对方接收:");
        //解码(解密)
        Base64.Decoder dc = Base64.getDecoder();
        byte[] bs1 = dc.decode(s1);
        byte[] bs2 = dc.decode(s2);

        String str1 = new String(bs1);//这是一个明文字符串
        String str2 = new String(bs2);//http://localhost:8080/itcast/index?username=张三&pwd=1111

        System.out.println("解密:");
        System.out.println(str1);
        System.out.println(str2);

    }
}

代码图解:

在这里插入图片描述

.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值