JDK8新特性
一、Lambda
函数式接口
//系统提供的函数式接口:消费型,供给型,函数型,断言型
//函数型接口: 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"));
扩展应用
//扩展函数式接口的应用场景:
//案例:使用集合存储多个字符串;
//需求: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;
}
}
方法引用
对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不能再使用
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);
Stream中间操作
class Student{
String name;
int age;
public Student(){}
public Student(String name,int age) {
this.name=name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int hashCode() {
//...
return result;
}
@Override
public boolean equals(Object obj) {
//...
return true;
}
}
public class Test2 {
public static void main(String[] args) {
//Stream的中间操作:
//案例:容器中存自定义对象,通过Stream中间过程操作
List<Student> list = new ArrayList<Student>();
list.add(new Student("凤姐", 25));
list.add(new Student("郭德纲", 50));
list.add(new Student("赵本山", 60));
list.add(new Student("姚明", 40));
list.add(new Student("刘亦菲", 35));
list.add(new Student("姚明", 40));
//filter方法:过滤 需求:<40的显示
list.stream().filter(st->st.age<40).forEach(System.out::println);
System.out.println("------");
//limit:限制只能拿4个元素 skip:跳过2个 可链式编程
list.stream().limit(4).skip(2).forEach(System.out::println);
System.out.println("---去重---");
//distinct:需要自定义类重写hashcode和equals
list.stream().distinct().forEach(System.out::println);
System.out.println("---排序---");
//sorted:排序-按属性排,例如年龄
list.stream().sorted((s1,s2)->s1.age-s2.age).forEach(System.out::println);
System.out.println("---map映射---");
//map:将元素映射成元素的属性,放到Stream中
list.stream().map(st->st.name).forEach(System.out::println);
System.out.println("---------"); //parallel:多线程存储
list.stream().parallel().forEach(System.out::println);
}
}
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则会出现日期的混乱。
本地日期与时间戳
//本地日期: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);
日期转换
//日期的转换: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);
格式化日期类
DateTimeFormatter格式化日期类,类似于Date中的SimpleDateFormat。可以给本地日期转格式
//格式化日期类:传入日期和时间格式
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
String strDate = dtf.format(LocalDateTime.now());
System.out.println(strDate);
四、总结与作业
总结
作业
1.应用案例: 集合存储字符串元素,例如: "Ldh","guodegang","lyf","Gyy","liuyifei"
1.找出集合中包含y的元素; 2. 找出集合中含有大写字母的元素
方式1:使用常规的集合操作求出----循环遍历后判定
方式2:使用lambda表达式来操作----提示:断言型接口
2.使用Stream进行排序, Stream中操作Person对象,里面有name,age属性,按照年龄进行降序排列
3.Stream中操作Person对象的,里面有name,age属性,请使用map映射,遍历出Peson的name属性