目录
一、Lambda
概述:Lambda是jdk8提供的新特性;就是匿名内部类的简写;能用匿名内部类,则可使用lambda表达式
匿名内部类往往常用于接口实现多态的方式中,所以lambda表达式语法也类似,需要有接口引用
语法:
接口引用 = (重写方法参数)->{重写方法体}
1.应用
//案例:
Runnable run = new Runnable() {
@Override
public void run() {
System.out.println("匿名内部类");
}
};
Thread th = new Thread(run);
th.start();
//lambda表达式
Runnable run2 = ()->System.out.println("lambda表达式");
Thread th2 = new Thread(run2);
th2.start();
2.函数式接口
函数式接口也是lambda表达式的应用场景,只不过接口有特殊定义:接口中的抽象方法只有一个
//函数式接口的应用:
//案例:飞天娃具有飞天的能力
@FunctionalInterface //函数式接口的注解
interface Flyable{
void fly(); //函数式接口只能有一个抽象方法
}
public class Test2 {
public static void main(String[] args) {
new Flyable() {
@Override
public void fly() {
System.out.println("匿名的飞天能力");
}
}.fly();
//lambda表达式
Flyable ff = ()->System.out.println("lambda的飞天能力");
ff.fly();
//lambda细节:
//1.根据接口引用可以自动识别lambda表达式结构及调用重写方法
//2.重写方法体中如果只有一句,则可省略{}以及省略return
//3.如果只有一个参数,则可省略()
//4.lambda不能生成独立的内部类文件
}
}
案例2:
//系统提供的函数式接口:消费型,供给型,函数型,断言型
//函数型接口: Function
//说明:参数为Integer,返回值为String--->Integer转String
Function<Integer, String> fun = i->i+"";
System.out.println(fun.apply(666));
//断言型接口:Predicate
Predicate<String> pre = s->s.endsWith("llo");
System.out.println(pre.test("hello"));
3.系统提供的函数式接口
/函数式接口主要有4个:消费型接口,供给型,函数型,断言型
//消费型接口:有参数无返回值方法
//供给型接口:无参数有返回值方法
//函数型接口:有参数有返回值方法-参数和返回值只要是引用类型即可
//断言型接口:有参数有返回值方法-返回类型为boolean类型
//消费型接口:Consumer
Consumer<Integer> con = s->System.out.println("消费了--"+s);
con.accept(666);
//供给型接口:Supplier
Supplier<Integer> sup = ()->new Random().nextInt(6);
System.out.println(sup.get());
4.扩展应用:
//扩展函数式接口的应用场景:
//案例:使用集合存储多个字符串;
//需求:1.找出以"l"开头的元素 2.找出长度大于5的元素
public class Test2 {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("lhp");
list.add("fengjie");
list.add("liudehua");
list.add("gdg");
list.add("zhaobs");
List<String> l1 = getStartL(list); //获取出以l开头的元素
System.out.println(l1);
List<String> l2 = getLength(list); //获取出以l开头的元素
System.out.println(l2);
//使用断言型处理: 传参lambda--维护性更强
List<String> l3 = getList(list,s->s.startsWith("l"));
System.out.println("l开头:"+l3);
List<String> l4 = getList(list,s->s.length()>5);
System.out.println("长度大于5:"+l4);
}
private static List<String> getList(List<String> list,Predicate<String> pre) {
List<String> l = new ArrayList<String>();
for(String a:list) {
if(pre.test(a)) { //接口回调,谁传给接口引用,我就调谁
l.add(a);
}
}
return l;
}
private static List<String> getLength(List<String> list) {
List<String> l = new ArrayList<String>();
for(String a:list) {
if(a.length()>5) {
l.add(a);
}
}
return l;
}
private static List<String> getStartL(List<String> list) {
List<String> l = new ArrayList<String>();
for(String a:list) {
if(a.startsWith("l")) {
l.add(a);
}
}
return l;
}
}
5.方法引用
对lambda表达式的简化写法(了解);是一种固定的写法格式,后续用得较少
//方法引用:lambda表达式的简写
//消费型接口:Consumer
Consumer<Integer> con = i->System.out.println("消费:"+i);
con.accept(666);
//方法引用:固定形式的写法-无法灵活变动
//场景:循环遍历打印时可直接写方法引用
Consumer<Integer> con2 = System.out::println;
con2.accept(555);
二、Stream流
概述:类似集合用法,是一个容器的应用;只不过集合关注存数据;Stream关注的是操作过程
应用:
Stream创建 2. 中间操作过程 3. 终止结果
说明:Stream调用操作方法,返回的依然是Stream;意味着可以进行链式编程
链式编程:可以将Stream方法连续性的调用
注意:Stream调用终止结果方法则Stream不能再使用
1.Stream的创建
//Stream的创建:
List<String> list = new ArrayList<String>();
list.add("zs");
list.add("ls");
list.add("ww");
//1.通过List集合方式创建Stream
//parallelStream:多线程的方式放入Stream中-无序 stream:有序存储
//forEach:是终止操作,此处为了遍历出Stream结果
list.stream().forEach(System.out::println);
System.out.println("---------------");
//2.通过Arrays方式
String[] a = {"zz","bb","cc"};
Arrays.stream(a).forEach(System.out::println);
System.out.println("---------------");
//3.Stream的静态方法
Stream.of(a).forEach(System.out::println);
//IntStream:专门操作int容器的
System.out.println("---------------");
int[] b = {3,5};
IntStream.of(b).forEach(System.out::println);
2.Stream终止结果
class Person{
String name;
int age;
public Person() {}
public Person(String name,int age) {
this.name = name;
this.age = age;
}
}
public class Test3 {
public static void main(String[] args) {
//Stream终止操作:
Student[] sts = {new Student("zs", 30),new Student("ls", 40),new Student("ww", 35),new Student("zl", 26)};
//forEach:循环遍历Sream的元素
Arrays.stream(sts).forEach(System.out::println);
System.out.println("---max---");
//需求:求年龄最大:max
System.out.println(Arrays.stream(sts).max((s1,s2)->s1.age-s2.age).get());
System.out.println("---min---");
System.out.println(Arrays.stream(sts).min((s1,s2)->s1.age-s2.age).get());
System.out.println("---count---");
System.out.println(Arrays.stream(sts).count());
System.out.println("---reduce---");
//reduce:汇总:基于元素值汇总--结合map使用
System.out.println(Arrays.stream(sts).map(st->st.age).reduce((a1,a2)->a1+a2).get());
System.out.println("---collect---");
//collect:集合转换 toList--转成List集合
List<Student> list = Arrays.stream(sts).collect(Collectors.toList());
System.out.println(list);
}
}
三、本地日期
前面的Date只是在单线程中使用的日期类,在多线程中需要使用本地日期;如果多线程中使用Date则会出现日期的混乱。
1.本地日期与时间戳
//本地日期:LocalDate,LocalTime,LocalDateTime
LocalDate ld = LocalDate.now(); //本地日期
System.out.println(ld);
System.out.println(LocalTime.now()); //本地时间
System.out.println(LocalDateTime.now()); //本地日期时间
Instant instant = Instant.now(); //获取时间戳--世界的时间-和我们本地时间差8小时
System.out.println(instant);
ZoneId zoneId = ZoneId.systemDefault();
System.out.println(zoneId); //Asia/Shanghai
Set<String> sets = ZoneId.getAvailableZoneIds(); //获取所有时区
System.out.println(sets);
2.日期转换
//日期的转换:Date->本地时间
Date date = new Date();
Instant instant = date.toInstant(); //date转Instant
System.out.println(instant);
//Instant(需要设置默认时区)->本地时间
LocalDateTime ldt = instant.atZone(ZoneId.systemDefault()).toLocalDateTime();
System.out.println(ldt);
//本地时间-->Date
//LocalDateTime->Instant
Instant in = ldt.atZone(ZoneId.systemDefault()).toInstant();
//Instant->Date
Date date2 = Date.from(in);
System.out.println(date2);
3.格式化日期类
DateTimeFormatter格式化日期类,类似于Date中的SimpleDateFormat。可以给本地日期转格式
//格式化日期类:传入日期和时间格式
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
String strDate = dtf.format(LocalDateTime.now());
System.out.println(strDate);