代理设计模式原理 使用一个代理将对象包装起来,然后用该代理对代替原始对象。任何对原始对象的调用都要通过代理对象。代理对象决定是否以及何时调用转到原始对象上。
动态代理是指客户通过代理类来调用其他对象上的方法,并且是在程序运行时根据需要来动态创建目标类的代理对象。
动态代理的使用场景:
动态代理相较于静态代理的优点:
抽象角色中(接口)声明的所有方法都被转移到调用处理器集中的方法中处理,这样我们可以更加灵活和统一的处理众多方法。
静态代理方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 package com.songzx.proxy;public class StaticProxyTest { public static void main (String[] args) { ProxyCloth proxyCloth = new ProxyCloth(new NickCloth()); proxyCloth.productCloth(); } } interface ClothFactory { void productCloth () ; } class ProxyCloth implements ClothFactory { private ClothFactory factory; public ProxyCloth (ClothFactory factory) { this .factory = factory; } @Override public void productCloth () { System.out.println("代理类准备调用被代理类" ); factory.productCloth(); System.out.println("代理类调用完毕" ); } } class NickCloth implements ClothFactory { public NickCloth () { } @Override public void productCloth () { System.out.println("nick工厂加工鞋子" ); } }
动态代理实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 package com.songzx.proxy;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class ProxyClass { public static void main (String[] args) { SuperMan superMan = new SuperMan(); Person proxyFactory = (Person) ProxyFactory.getProxyFactory(superMan); String desc = proxyFactory.eat("牛肉" ); System.out.println(desc); String s = proxyFactory.MyHeight(); System.out.println(s); } } interface Person { String MyHeight () ; String eat (String food) ; } class SuperMan implements Person { @Override public String MyHeight () { return "我的身高是199cm" ; } @Override public String eat (String food) { System.out.println("我喜欢吃的食物是" + food); return food; } } class ProxyFactory { public static Object getProxyFactory (Object obj) { Class<?> aClass = obj.getClass(); MyInvocationHandler ih = new MyInvocationHandler(); ih.bind(obj); return Proxy.newProxyInstance(aClass.getClassLoader(), aClass.getInterfaces(), ih); } } class MyInvocationHandler implements InvocationHandler { private Object obj; public void bind (Object obj) { this .obj = obj; } @Override public Object invoke (Object proxy, Method method, Object[] args) throws Throwable { Object invoke = method.invoke(obj, args); return invoke; } }
Java8新特性示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 package com.songzx.java8;import org.junit.Test;import java.util.Comparator;public class Exer1 { @Test public void test1 () { Runnable r1 = new Runnable() { @Override public void run () { System.out.println("我爱中国" ); } }; r1.run(); System.out.println("************" ); Runnable r2 = ()-> System.out.println("我爱中国" ); r2.run(); } @Test public void test2 () { Comparator<Integer> c1 = new Comparator<Integer>() { @Override public int compare (Integer o1, Integer o2) { return Integer.compare(01 ,02 ); } }; int compare = c1.compare(12 , 13 ); System.out.println(compare); Comparator<Integer> c2 = (o1,o2) -> Integer.compare(o1,o2); int compare1 = c2.compare(13 , 12 ); System.out.println(compare1); Comparator<Integer> c3 = Integer :: compare; int compare2 = c3.compare(5 , 2 ); System.out.println(compare2); } }
Lambda 表达式语法
语法1 省略类的new过程
语法2 省略大括号和return
语法3 只有一个参数时省略小括号
语法4 多个参数和多个方法体
语法5 无参无返回
Lambda表达式的本质:作为函数式接口的实例
使用Lambda表达式的要求:实现类必须有且只有一个重写方法时
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 package com.songzx.java8;import org.junit.Test;import java.util.Comparator;import java.util.function.Consumer;public class Lambda1 { @Test public void test1 () { Comparator<Integer> c = (o1, o2) -> { return Integer.compare(o1,o2); }; System.out.println(c.compare(10 , 11 )); Comparator<Integer> c2 = (o1, o2) -> Integer.compare(o1,o2); System.out.println(c2.compare(10 , 11 )); Consumer<String> c3 = s -> System.out.println(s); c3.accept("小不忍则乱大谋" ); Comparator<Integer> c4 = (o1, o2) -> { System.out.println(o1); System.out.println(o2); return Integer.compare(o1,o2); }; System.out.println(c4.compare(21 , 12 )); Runnable r = ()-> System.out.println("无参无返回" ); r.run(); } }
函数式接口
只包含一个抽象方法的接口称为函数式接口
可以通过 Lambda 表达式来创建该接口的对象
可以在一个接口上使用 @FunctionalInterface 注解,这样做可以查看这个接口是否是一个函数式接口
自定义函数式接口 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 package com.songzx.java8;public class Lambda2 { public static void main (String[] args) { TestLambda t = () -> "自定义接口使用 Lambda" ; System.out.println(t.show()); } } @FunctionalInterface interface TestLambda { String show () ; }
Java内置四大核心函数式接口
函数式接口
参数类型
返回类型
用途
Consumer 消费型接口
T
void
为类型为T的对象应用操作,包含方法 void.accept(T t)
Supplier 供给型接口
无
T
返回类型为 T 的对象,包含方法 T.get()
Function<T,R> 函数型接口
T
R
为类型为T的对象应用操作,并返回结果,结果是R类型的对象,包含方法 R.apply(T t)
Predicate
T
Boolean
确定类型为T的对象是否满足某约束,并返回boolean值,包含方法 boolean test(T)
Consumer 接口的使用 1 2 3 4 5 6 7 8 9 @Test public void test1 () { happyTome(200 , money -> System.out.println("今日消费" + money)); } public void happyTome (double money, Consumer<Double> con) { con.accept(money); }
Supplier 接口的使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Test public void test2 () { int [] ints = {45 , 65 , 84 , 12 , 1 }; int maxInt = getMax(() -> { int max = ints[0 ]; for (int anInt : ints) { if (anInt > max) { max = anInt; } } return max; }); System.out.println(maxInt); } public int getMax (Supplier<Integer> sup) { return sup.get(); }
Predicate 接口的使用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @Test public void test3 () { List<String> strings = Arrays.asList("北京" , "南京" , "东京" , "天津" , "普京" ); List<String> filterStr1 = filterStr(strings, new Predicate<String>() { @Override public boolean test (String s) { return s.contains("京" ); } }); System.out.println(filterStr1); List<String> filterlist = filterStr(strings, s -> s.contains("京" )); System.out.println(filterlist); } public List<String> filterStr (List<String> list, Predicate<String> pre) { ArrayList<String> list1 = new ArrayList<>(); for (String s : list) { if (pre.test(s)){ list1.add(s); } } return list1; }
方法引用的使用
使用情景:当要传递给 Lambda 体的操作已经有实现的方法,可以使用方法引用
方法引用:本质就是 Labmda 表达式,而 Lambda 表达式作为函数式接口的实例,所以方法引用也是函数式接口的实例
使用格式:类(或对象) :: 方法名
具体分为如下三种情况:
对象 :: 非静态方法
类 :: 静态方法
类 :: 非静态方法
方法引用的使用要求:要求接口中的抽象方法的形参列表和返回值要与方法引用的方法形参列表和返回值类型相同
定义一个测试类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 package com.songzx.java8;public class EmployeeTest { String name; int age; double money; public EmployeeTest () { } public EmployeeTest (String name, int age, double money) { this .name = name; this .age = age; this .money = money; } 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; } public double getMoney () { return money; } public void setMoney (double money) { this .money = money; } @Override public String toString () { return "EmployeeTest{" + "name='" + name + '\'' + ", age=" + age + ", money=" + money + '}' ; } }
情况一:对象引用非静态方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 package com.songzx.java8;import org.junit.Test;import java.beans.Customizer;import java.io.PrintStream;import java.util.Comparator;import java.util.function.Consumer;import java.util.function.Supplier;public class Lambda5 { @Test public void test1 () { PrintStream pr = System.out; Consumer<String> con = pr::println; con.accept("Hello world" ); EmployeeTest tome = new EmployeeTest("Tome" , 18 , 6000 ); Supplier<String> sup = tome :: getName; System.out.println(sup.get()); } }
情况二:类引用静态方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 package com.songzx.java8;import org.junit.Test;import java.util.Comparator;import java.util.function.Function;public class Lambda6 { @Test public void test () { Comparator<Integer> com = Integer :: compare; System.out.println(com.compare(12 , 32 )); Function<Double,Long> fun = Math :: round; System.out.println(fun.apply(12.6 )); Function<Double,Long> fun2 = d -> Math.round(d); System.out.println(fun2.apply(12.3 )); Function<Double,Long> fun3 = new Function<Double, Long>() { @Override public Long apply (Double aDouble) { return Math.round(aDouble); } }; System.out.println(fun3.apply(12.3 )); } }
情况三:类引用实例方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package com.songzx.java8;import org.junit.Test;import java.util.Comparator;import java.util.function.BiPredicate;import java.util.function.Function;public class Lambda7 { @Test public void test () { Comparator<String> com = (s1,s2) -> s1.compareTo(s2); System.out.println(com.compare("a" , "b" )); Comparator<String> com1 = String :: compareTo; System.out.println(com1.compare("a" , "b" )); } @Test public void test1 () { BiPredicate<String,String> bip = (s1,s2) -> s1.equals(s2); System.out.println(bip.test("hello" , "hello" )); BiPredicate<String,String> bip2 = String :: equals; System.out.println(bip2.test("he" , "he" )); } @Test public void test2 () { EmployeeTest emp = new EmployeeTest("Tome" , 15 , 6000 ); Function<EmployeeTest,String> fun = e -> e.getName(); System.out.println(fun.apply(emp)); Function<EmployeeTest,String> fun2 = EmployeeTest :: getName; System.out.println(fun2.apply(emp)); } }
构造器引用 和方法引用类似,函数式接口的抽象方法的形参列表和构造器的参数列表相同,抽象方法的返回值类型即为构造器所属类的类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package com.songzx.java8;import javafx.scene.layout.VBox;import org.junit.Test;import java.util.function.BiFunction;import java.util.function.Function;import java.util.function.Supplier;public class Lambda8 { @Test public void test1 () { Supplier<EmployeeTest> sup = ()-> new EmployeeTest(); System.out.println(sup.get()); Supplier<EmployeeTest> sup1 = EmployeeTest::new ; System.out.println(sup1.get()); } @Test public void test2 () { Function<Integer,EmployeeTest> fun = age -> new EmployeeTest(age); System.out.println(fun.apply(15 )); Function<Integer,EmployeeTest> fun1 = EmployeeTest::new ; System.out.println(fun1.apply(16 )); } @Test public void test3 () { BiFunction<String,Integer,EmployeeTest> bif = (name,age) -> new EmployeeTest(name,age); System.out.println(bif.apply("Tome" , 15 )); BiFunction<String,Integer,EmployeeTest> bif2 = EmployeeTest::new ; System.out.println(bif2.apply("Tome" , 15 )); } }
数组引用 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.songzx.java8;import org.junit.Test;import java.sql.Array;import java.util.Arrays;import java.util.function.Function;import java.util.function.Supplier;public class Lambda9 { @Test public void test () { Function<Integer,String[]> fun = len -> new String[len]; String[] strings = fun.apply(5 ); System.out.println(Arrays.toString(strings)); Function<Integer,Integer[]> fun2 = Integer[] :: new ; Integer[] integers = fun2.apply(5 ); System.out.println(Arrays.toString(integers)); } }
什么是 Stream 是数据渠道,用于操作数据(集合,数组等)所生成的元素序列。更注重计算,不会破坏原来的数据,会返回一个计算好的数据。
Stream 特点:
Stream 自己不会存储元素
Stream 不会改变源对象,相反,他们会返回一个持有结果的新 Stream
Stream 操作是延迟执行的。这表示他们会等到需要结果时再执行
Stream 操作的三个步骤
1.创建Stream
2.中间操作
3.终止操作
一旦执行终止操作,中间操作才会执行,并产生结果,之后不会再被使用
Stream 的四种创建方式 方式一:通过集合创建Stream 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.songzx.Stream;import org.junit.Test;import java.util.ArrayList;import java.util.stream.Stream;public class ListStream { @Test public void test1 () { ArrayList<String> list = new ArrayList<>(); list.add("aa" ); list.add("bb" ); list.add("cc" ); Stream<String> stream = list.stream(); Stream<String> stringStream = list.parallelStream(); } }
方式二:通过数据创建Stream 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package com.songzx.Stream;import org.junit.Test;import java.util.Arrays;import java.util.stream.IntStream;public class ArrayStream { @Test public void test () { int [] ints = {1 , 2 , 3 , 4 , 5 , 6 }; IntStream stream = Arrays.stream(ints); } }
方式三:通过 Stream.of 创建 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 package com.songzx.Stream;import org.junit.Test;import java.util.stream.Stream;public class Streamof { @Test public void test () { Stream<Integer> integerStream = Stream.of(12 , 3 , 65 , 84 ); } }
方式四:创建Stream无限流 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 package com.songzx.Stream;import org.junit.Test;import java.util.stream.Stream;public class Streams { @Test public void test () { Stream.iterate(0 , t -> t + 1 ).limit(10 ).forEach(System.out::println); Stream.generate(Math::random).limit(10 ).forEach(System.out::println); } }
Stream 中间流 筛选和去重
使用 filter 方法过滤出符合条件的数据
skip(long n) 跳过前 n 个元素,显之后的元素,如果总元素个数不足n个则返回一个空的流
limit(long n) 显示前n个元素
distinct() 去除数据中重复的元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.songzx.Stream;import java.util.List;public class Stream1 { public static void main (String[] args) { List<User> users = User.getUsers(); users.stream().filter(user->user.getAge() >= 20 ).forEach(System.out::println); System.out.println("**********" ); users.stream().skip(2 ).forEach(System.out::println); System.out.println("**********" ); users.stream().limit(3 ).forEach(System.out::println); System.out.println("**********" ); users.stream().distinct().forEach(System.out::println); } }
Map映射
map 映射将集合中的元素转成大写
使用 flatMap 展开二级嵌套的 stream 集合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package com.songzx.Stream;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import java.util.stream.Stream;public class Stream2 { public static void main (String[] args) { List<String> strings = Arrays.asList("aa" , "bb" , "cc" , "dd" ); strings.stream().map(str->str.toUpperCase()).forEach(System.out::println); System.out.println("**********" ); List<User> users = User.getUsers(); users.stream().map(user->user.getName()).forEach(System.out::println); System.out.println("**********" ); Stream<Stream<Character>> streamStream = strings.stream().map(Stream2::getStringStream); streamStream.forEach(str->str.forEach(System.out::println)); System.out.println("**********" ); Stream<Character> characterStream = strings.stream().flatMap(Stream2::getStringStream); characterStream.forEach(System.out::println); } public static Stream<Character> getStringStream (String str) { ArrayList<Character> charlist = new ArrayList<>(); for (char c : str.toCharArray()) { charlist.add(c); } return charlist.stream(); } }
排序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package com.songzx.Stream;import java.util.Arrays;import java.util.List;public class Stream3 { public static void main (String[] args) { List<Integer> integers = Arrays.asList(12 , 65 , 0 , 32 , 1 , 215 , -25 ); integers.stream().sorted().forEach(System.out::println); List<User> users = User.getUsers(); users.stream().sorted((s1,s2)->{ int ageVal = Integer.compare(s1.getAge(),s2.getAge()); if (ageVal != 0 ){ return ageVal; }else { return Double.compare(s1.getHeight(),s2.getHeight()); } }).forEach(System.out::println); } }
Stream 结束语句 匹配和查找
allMatch 判断所有的人员年龄是否都大于20岁,必须所有数据都要满足才会返回true
anyMatch 判断是否有大于20岁的人员,满足一个即可返回true
noneMatch 判断是不是没有大于20的,如果条件成立返回false,条件不成立返回true
findFirst 返回集合中的第一个元素
findAny 返回集合中的任意元素
count 返回集合中的元素个数
max 返回集合中最大的年龄
min 返回集合中身高最低的人员
forEach 内部迭代
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 package com.songzx.Stream;import java.util.List;import java.util.Optional;import java.util.stream.Stream;public class Stream4 { public static void main (String[] args) { List<User> users = User.getUsers(); boolean b = users.stream().allMatch(user -> user.getAge() > 20 ); System.out.println(b); boolean b1 = users.stream().anyMatch(user -> user.getAge() > 20 ); System.out.println(b1); boolean b2 = users.stream().noneMatch(user -> user.getAge() > 20 ); System.out.println(b2); Optional<User> first = users.stream().findFirst(); System.out.println(first); Optional<User> any = users.stream().findAny(); System.out.println(any); long count = users.stream().count(); System.out.println(count); Optional<Integer> max = users.stream().map(user -> user.getAge()).max(Integer::compare); System.out.println(max); Optional<User> min = users.stream().min((u1, u2) -> Double.compare(u1.getHeight(), u2.getHeight())); System.out.println(min); users.stream().forEach(item-> System.out.println(item)); } }
归约 reduce 计算出来的结果会参与下一次的计算。reduce 方法的第一个参数表示初始值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 package com.songzx.Stream;import java.util.Arrays;import java.util.List;import java.util.Optional;public class Stream5 { public static void main (String[] args) { List<Integer> integers = Arrays.asList(1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ); Integer reduce = integers.stream().reduce(0 , Integer::sum); System.out.println(reduce); List<User> users = User.getUsers(); Integer reduce1 = users.stream().map(User::getAge).reduce(0 , Integer::sum); System.out.println(reduce1); Integer reduce2 = users.stream().map(user -> user.getAge()).reduce(0 , (a1, a2) -> a1 + a2); System.out.println(reduce2); } }
收集 collect 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 package com.songzx.Stream;import java.util.List;import java.util.Set;import java.util.stream.Collectors;public class Stream6 { public static void main (String[] args) { List<User> users = User.getUsers(); List<User> userList = users.stream().filter(user -> user.getAge() >= 15 ).collect(Collectors.toList()); userList.forEach(System.out::println); System.out.println("*********" ); Set<User> userSet = users.stream().filter(user -> user.getAge() >= 15 ).collect(Collectors.toSet()); for (User user : userSet) { System.out.println(user); } } }
Optional 类的创建
Optional.of(T)
不能存放为 null 的值
Optional.ofNullable(T)
可以存放 null 值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 package com.songzx.Optional;import org.junit.Test;import java.util.Optional;public class java1 { @Test public void test1 () { Boy boy = new Boy(); Optional<Boy> boy1 = Optional.of(boy); System.out.println(boy1); } @Test public void test2 () { Boy boy = new Boy(); boy = null ; Optional<Boy> boy1 = Optional.ofNullable(boy); System.out.println(boy1); } }
Optional 类的使用
orElse(T other)
该方法会判断原本的数据是否为空,如果数据为空则将 other 作为新值赋值给原来的数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 package com.songzx.Optional;import java.util.Optional;public class java2 { static String getBoyName (Boy boy) { if (boy != null ){ return boy.getName(); }else { return null ; } } static String getBoyName2 (Boy boy) { Optional<Boy> boyOptional = Optional.ofNullable(boy); Boy boy1 = boyOptional.orElse(new Boy("李四" )); return boy1.getName(); } public static void main (String[] args) { Boy boy = new Boy("张三" ); boy = null ; String boyName = getBoyName(boy); System.out.println(boyName); String boyName2 = getBoyName2(boy); System.out.println(boyName2); } }