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关注的是操作过程

应用:

  1. 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属性