阅读量:0
软件设计之Java入门视频(22)
视频教程来自B站尚硅谷:
尚硅谷Java入门视频教程,宋红康java基础视频
相关文件资料(百度网盘)
提取密码:8op3
idea 下载可以关注 软件管家 公众号
学习内容:
该视频共分为1-717部分
本次内容涉及 660-717(后续Java9、10、11新特性就不一一赘述)在写代码时,总是需要来回切换界面来看代码要求,这里推荐Snipaste,可以把截图以窗口形式放在屏幕上
记录内容:
- 静态代理
- 动态代理
- Lambda表达式
- 函数式接口
- 方法引用
- Stream API
1、静态代理
interface ClothFactory{ void produceCloth(); } //代理类 class ProxyClothFactory implements ClothFactory{ private ClothFactory factory;//用被代理对象进行实例化 public ProxyClothFactory(ClothFactory factory) { this.factory = factory; } @Override public void produceCloth() { System.out.println("代理工厂做准备工作"); factory.produceCloth(); System.out.println("代理工厂做后续工作"); } } //被代理类 class NikeClothFactory implements ClothFactory{ @Override public void produceCloth() { System.out.println("Nike工厂生产运动服"); } } public class StaticProxyTest { public static void main(String[] args) { //创建被代理类对象 NikeClothFactory ncf = new NikeClothFactory(); //创建代理类对象 ProxyClothFactory pcf = new ProxyClothFactory(ncf); pcf.produceCloth(); //代理工厂做准备工作 //Nike工厂生产运动服 //代理工厂做后续工作 } }
2、动态代理
interface Human{ String getBelief(); void eat(String food); } //被代理类 class SuperMan implements Human{ @Override public String getBelief() { return "I believe"; } @Override public void eat(String food) { System.out.println("我喜欢吃" + food); } } /* * 想要实现动态代理,需要解决的问题 * 问题1:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象 * 问题2:当通过代理类的对象调用方法时,如何动态的去调用被代理类中的同名方法*/ class ProxyFactory{ //调用此方法,返回一个代理类的对象,解决问题1 public static Object getProxyInstance(Object obj){//obj:被代理类的对象 MyInvocationHandler handler = new MyInvocationHandler(); handler.bind(obj); return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),handler); } } class MyInvocationHandler implements InvocationHandler{ private Object obj;//需要使用被代理类对象进行幅值 public void bind(Object obj){ this.obj = obj; } //通过代理类的对象,调用方法a时,会自动调用如下方法:invoke() //将被代理类要执行的方法a的功能声明在invoke()中 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法 //obj:被代理类对象 Object returnValue = method.invoke(obj, args); return returnValue; } } public class ProxyTest { public static void main(String[] args) { SuperMan superMan = new SuperMan(); //proxyInstance代理类的对象 Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan); proxyInstance.eat("四川麻辣");//我喜欢吃四川麻辣 } }
3、Lambda表达式
public class LambdaTest { //语法格式一:无参,无返回值 @Test public void test(){ Runnable r1 = new Runnable() { @Override public void run() { System.out.println("输出"); } }; r1.run(); System.out.println("***********"); Runnable r2 = () -> {System.out.println("输出2");}; r2.run(); } @Test //语法格式二:Lambda 需要一个参数,但是没有返回值。 public void test1(){ Consumer<String> con = new Consumer<String>(){ @Override public void accept(String s){ System.out.println(s); } }; con.accept("你好"); System.out.println("********"); Consumer<String> con1 = (String s) -> {System.out.println(s);}; } @Test //语法格式三:数据类型可以省略,因为可由编译器推断得出,称为“类型推断” public void test3(){ Consumer<String> con = new Consumer<String>(){ @Override public void accept(String s){ System.out.println(s); } }; con.accept("你好"); System.out.println("********"); Consumer<String> con1 = (s) -> {System.out.println(s);}; } @Test //语法格式四:Lambda 若只需要一个参数时,参数的小括号可以省略 public void test4(){ Consumer<String> con = new Consumer<String>(){ @Override public void accept(String s){ System.out.println(s); } }; con.accept("你好"); System.out.println("********"); Consumer<String> con1 = s -> {System.out.println(s);}; } @Test //语法格式五:Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值 public void test5(){ Comparator<Integer> com1 = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { System.out.println(o1); System.out.println(o2); return o1.compareTo(o2); } }; System.out.println("**********"); Comparator<Integer> com2 = (o1,o2) -> { System.out.println(o1); System.out.println(o2); return o1.compareTo(o2); }; System.out.println(com2.compare(12,6)); } @Test //语法格式六:当 Lambda 体只有一条语句时,return 与大括号若有,都可以省略 public void test6(){ Comparator<Integer> com1 = (o1,o2) -> o1.compareTo(o2);; System.out.println(com1.compare(12,6)); } }
4、函数式接口
5、方法引用
使用情景
:当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用
方法引用本身上就是Lamda表达式
,即也是函数式接口的实例
具体分为三种情况
:
1) 对象 :: 非静态方法
2)类::静态方法
3)类::非静态方法
public class LambdaTest { //情况一: 对象::实例方法 //Consumer中的void accept(T t) //PrintStream中的void println(T t) @Test public void test(){ Consumer<String> con1 = str -> System.out.println(str); con1.accept("北京"); System.out.println("**********"); PrintStream ps = System.out; Consumer<String> con2 = ps::println; con2.accept("beijing"); } // @Test //情况二: 类::静态方法 //Comparator 中的int compare(T t1, T t2) //Integer 中的int compare(T t1, T t2) public void test1(){ Comparator<Integer> com1 = (t1,t2) -> Integer.compare(t1,t2); System.out.println(com1.compare(12,13)); Comparator<Integer> com2 = Integer ::compare; System.out.println(com2.compare(12,13)); } @Test //情况三: 类::实例方法 //Comparator中的int compare(T t1,T t2) //String 中的int t1.compareTo(t2) public void test3(){ Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2); System.out.println(com1.compare("abc","def")); System.out.println("*********"); Comparator<String> com2 = String ::compareTo; System.out.println(com2.compare("abc","def")); } }
6、Stream API
1、
Stream
关注的是对数据的运算
,与CPU
打交道
2、集合
关注的是数据的存储
,与内存
打交道
3、注意点
①Stream 自己不会存储元素。
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream
③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
创建Stream
public class StreamAPITest { //创建Stream方式一:通过集合 @Test public void test1(){ List<Employee> employees = EmployeeData.getEmployees(); //default Stream<E> stream():返回一个顺序流 Stream<Employee> stream = employees.stream(); //default Stream<E> parallelStream():返回一个并行流 Stream<Employee> employeeStream = employees.parallelStream(); } //创建Stream方式二:通过数组 @Test public void test2(){ int[] arr = new int[]{1,2,3}; // 调用Arrays类的static <T> Stream<T> stream(T[] array): 返回一个流 IntStream stream = Arrays.stream(arr); Employee e1 = new Employee(1001,"Tom"); Employee e2 = new Employee(1002,"Jerry"); Employee[] arr1 = new Employee[]{e1,e2}; Stream<Employee> stream1 = Arrays.stream(arr1); } //创建 Stream方式三:通过Stream的of() @Test public void test3(){ Stream<Integer> stream = Stream.of(1,2,3); } }
中间操作:筛选
public class StreamAPITest { //创建Stream方式一:通过集合 @Test public void test1() { List<Employee> list = EmployeeData.getEmployees(); //filter(Predicate p)——接收Lambda,从流中排除某些元素 Stream<Employee>stream = list.stream(); stream.filter(e -> e.getSalary() > 7000).forEach(System.out ::println); System.out.println(); //limit(long maxSize) 截断流,使其元素不超过给定数量 list.stream().limit(3).forEach(System.out ::println); System.out.println(); //skip(long n) //跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流与 limit(n) 互补 list.stream().skip(3).forEach(System.out ::println); //distinct() 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素 list.add(new Employee(1010,"刘强东",40,8000)); list.add(new Employee(1010,"刘强东",40,8000)); list.add(new Employee(1010,"刘强东",40,8000)); list.stream().distinct().forEach(System.out ::println); }
中间操作:映射
@Test public void test2() { // map(Function f)接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。 List<String> list = Arrays.asList("aa","bb"); list.stream().map(str -> str.toUpperCase()).forEach(System.out ::println); Stream<Stream<Character>> streamStream = list.stream().map(StreamAPITest::fromStringToStream); streamStream.forEach(s ->{ s.forEach(System.out ::println); }); //flatMap(Function f)接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流 Stream<Character> characterStream = list.stream().flatMap(StreamAPITest::fromStringToStream); characterStream.forEach(System.out::println); } //将字符串中多个字符构成的集合转换为对应的Stream的实例 public static Stream<Character> fromStringToStream(String str){ ArrayList<Character> list = new ArrayList<>(); for (Character c : str.toCharArray()){ list.add(c); } return list.stream(); }
中间操作:排序
public class StreamAPITest { //排序 @Test public void test2() { //sorted()——自然排序 List<Integer> list = Arrays.asList(12, 43, 11, 22, 8, 16); list.stream().sorted().forEach(System.out::println); //抛异常,原因:Employee没有实现Comparable接口 // List<Employee> employees = EmployeeData.getEmployees(); // employees.stream().sorted().forEach(System.out::println); //sorted(Comparator com)——定制排序 List<Employee> employees = EmployeeData.getEmployees(); employees.stream().sorted((e1,e2) -> { return Integer.compare(e1.getAge(),e2.getAge()); }).forEach(System.out::println); } }
终止操作:匹配与查找
public class StreamAPITest { //匹配与查找 @Test public void test2() { List<Employee> employees = EmployeeData.getEmployees(); // allMatch(Predicate p) 检查是否匹配所有元素 boolean allMatch = employees.stream().allMatch(e ->e.getAge() > 18); System.out.println(allMatch); // anyMatch(Predicate p) 检查是否至少匹配一个元素 boolean anyMatch = employees.stream().anyMatch(e ->e.getAge() > 18); System.out.println(anyMatch); // noneMatch(Predicate p) 检查是否没有匹配所有元素 boolean noneMatch = employees.stream().noneMatch(e ->e.getAge() > 100); System.out.println(noneMatch); // findFirst() 返回第一个元素 Optional<Employee> employee = employees.stream().findFirst(); System.out.println(employee); // forEach(Consumer c) 内部迭代 employees.stream().forEach(System.out::println); //使用集合的遍历操作 employees.forEach(System.out::println); } }
终止操作:归约
//归约 @Test public void test2() { // reduce(T identity, BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。返回 T //计算1-10自然数和 List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10); Integer sum = list.stream().reduce(0, Integer::sum); System.out.println(sum); // reduce(BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。返回 Optional<T> List<Employee> employees = EmployeeData.getEmployees(); Stream<Double> salaryStream = employees.stream().map(Employee::getSalary); Optional<Double> sumMoney = salaryStream.reduce(Double::sum); System.out.println(sumMoney); }
终止操作:收集
//收集 @Test public void test2() { // collect(Collector c)将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法 List<Employee> employees = EmployeeData.getEmployees(); List<Employee> employeeList = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toList()); employeeList.forEach(System.out::println); Set<Employee> employeeSet = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toSet()); employeeSet.forEach(System.out::println); }