java8新特性lambda表达式, 函数式接口以及Steam流和新的日期时间例子代码

时间:2021-08-03 19:04:26

java8新特性lambda表达式, 函数式接口以及Steam流和新的日期时间例子代码


package com.zheng;

import java.io.IOException;
import java.nio.*
import java.time.*
import java.util.*

public class Java8 {
	public static void main(String[] args) {
		// 1. 谓词: predicate,即一个返回Boolean值的函数

		// 2. Lambda表达式:没有函数名的函数,但有参数列表,有函数主体,有返回值但没有返回语句(隐含return);可作为参数传递给方法
		// 2.1 基本语法(parameters)->expression
		// 2.2 基本语法(parameters)->{expression1; expression2}
		// 2.3 布尔表达式 (List<String> list) -> list.isEmpty()
		// 2.4 创建对象 () -> new User()
		// 2.5 消费一个对象 (User u) -> System.out.println(u.getAge())
		// 2.6 从一个对象选择/抽取 (String s) -> s.length()
		// 2.7 组合两个值 (int x,int y) -> x*y
		// 2.8 比较两个对象 (User u1,User u2) -> u1.getAge().compareTo(u2.getAge())
		List<User> list1 = Arrays.asList(new User("u1", 10), new User("u2", 20), new User("u3", 30), new User("u4", 30));
		list1.sort((u1, u2) -> u1.getAge().compareTo(u2.getAge()));
		list1.sort(Comparator.comparing(User::getName));

		// 3. 函数式接口: 只定义一个抽象方法的接口, 如java.util.Comparator和java.lang.Runnable
		// 3.1 lambda表达式允许直接以内联的形式为函数式接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例
		// 3.2 @FunctionalInterface注解表示将某个接口设计成一个函数式接口,如Runnable;该注解不是必须的
		// 3.3 创建一个线程
		Thread t = new Thread(() -> {
			System.out.println("run method");
			System.out.println("code");
		});
		t.start();
		// 3.4 jdk8提供的函数式接口java.util.function.Predicate<T>,
		// java.util.function.Consumer<T>, java.util.function.Function<T, R>
		// 3.5 Predicate<T>定义了一个test抽象方法,接受泛型参数T对象,返回一个boolean
		Predicate<List<User>> p1 = (List<User> list) -> list1.isEmpty();
		System.out.println("list1是否为空: " + p1.test(list1));
		IntPredicate a = (int i) -> i % 2 == 0;// LongPredicate,DoublePredicate
		System.out.println("9是否能被2除尽: " + a.test(9));
		// 3.6 Consumer<T>定义了一个accept抽象方法,接受泛型参数T对象,没有返回
		Consumer<User> c1 = (User u) -> {
			u.setAge(10);
			System.out.println("设置对象的age为: " + u.getAge());
		};
		c1.accept(new User("u1", 20));
		User u = new User("u1", 30);
		setUserAge(u, (User u1) -> u1.getName().equals("u1"), (User u1) -> u1.setAge(100));
		System.out.println("consumer: " + u.getAge());
		// 3.7 Function<T, R>定义了一个apply抽象方法,接受泛型参数T对象,返回泛型R对象
		Function<String, User> f1 = (String name) -> new User(name);
		f1.apply("u2");
		// 3.8 其它常用函数式接口
		// Supplier<T>: ()->T, UnaryOperation<T>: T->T,
		// BinaryOperation<T>: (T,T)->T, BiPredicate<L,R>: (L,R)->boolean,
		// BiConsumer<L,U>: (L,U)->void, BiFunction<T,U,R>: (T,U)->R

		// 4. 方法引用
		Function<String, User> f2 = User::new;
		f2.apply("123456");

		// 5. 复合lambda表达式
		// 5.1 排序后的逆序
		list1.sort(Comparator.comparing(User::getName).reversed());
		// 5.2 比较器链: 先按name排序后按age排序
		list1.sort(Comparator.comparing(User::getName).thenComparing(User::getAge));
		// 5.3 谓词复合
		Predicate<User> p11 = u11 -> u11.getAge() > 10;
		Predicate<User> p12 = p11.negate();// 非
		Predicate<User> p13 = p12.and(u11 -> u11.getAge() < 100);// 与
		Predicate<User> p14 = p13.or(u11 -> u11.isSex());// 或
		// 5.4 函数复合
		Function<Integer, Integer> f11 = x -> x + 1;
		Function<Integer, Integer> f12 = x -> x - 1;
		Function<Integer, Integer> f13 = f11.andThen(f12);

		// 6. 流: 遍历数据集的高级迭代器, 可透明的并行的处理任务
		// 6.1 筛选到list
		List<String> list2 = list1.stream()// stream换成parallelStream可实现多线程并行处理
				.filter(u6 -> u6.isSex())// 筛选
				.sorted(Comparator.comparing(User::getAge).reversed())// 排序
				.map(User::getName)// 提取名称
				.limit(10)// 只取10个, 还有distinct(),count(),skip()等方法
				.collect(Collectors.toList());// 创建list并保存数据
		System.out.println(list2);
		// 6.2 筛选到map,groupingBy(f)其实是groupingBy(f,toList())的缩写
		Map<Integer, List<User>> map2 = list1.stream().collect(Collectors.groupingBy(User::getAge));
		System.out.println(map2);
		// 6.3 遍历
		list2.forEach(s -> System.out.println("打印list2中的值: " + s));
		map2.forEach((k, v) -> System.out.println("键: " + k + ", 值: " + v));
		// 6.4 Arrays.stream(): 接受一个数组并产生一个流
		List<Stream<String>> list3 = list1.stream().map(u6 -> u6.getName().split("")).map(Arrays::stream).distinct().collect(Collectors.toList());
		// 6.5 flatMap得到扁平化流
		List<String> list4 = list1.stream().map(u6 -> u6.getName().split("")).flatMap(Arrays::stream).distinct().collect(Collectors.toList());
		System.out.println("flatMap: " + list4);
		// 6.6 anyMatch,allMatch,noneMatch
		System.out.println("anyMatch: " + list1.stream().anyMatch(u6 -> u6.getAge() == 10));
		// 6.7 findFirst,findAny
		Optional<User> o1 = list1.stream().filter(u6 -> u6.getAge() >= 200).findAny();
		System.out.println("findAny: " + o1.isPresent());
		// 6.8 reduce: 归约
		int ageSum = list1.stream().map(User::getAge).reduce(0, Integer::sum);
		// 6.9 mapToInt, mapToLong, mapToDouble
		ageSum = list1.stream().mapToInt(User::getAge).sum();// 这里还有max(),min(),average()等方法
		// 6.10 转换为对象流
		IntStream is1 = list1.stream().mapToInt(User::getAge);
		Stream<Integer> s2 = is1.boxed();
		// 6.11 OptionalInt,OptionalDouble,OptionalLong
		OptionalInt i1 = list1.stream().mapToInt(User::getAge).max();
		i1.orElse(100);// 如果没有则提供默认值
		// 6.12 数值范围 rangeClosed()
		IntStream is2 = IntStream.rangeClosed(1, 100);
		System.out.println("rangeClosed: " + is2.count());
		// 6.13 Stream.of构建流
		Stream<String> s3 = Stream.of("a", "b", "c", "d", "e", "f");
		s3.forEach(s33 -> System.out.println("Stream.of: " + s33));
		// 6.14 由数组创建流
		int sum = Arrays.stream(new int[] { 1, 2, 3, 4, 5, 6 }).sum();
		System.out.println("Arrays.stream: " + sum);
		// 6.15 由文件生成流
		try {
			Stream<String> lines = Files.lines(Paths.get("/Users/zhengyongfei/Desktop/ms.txt"), Charset.defaultCharset());
			System.out.println(lines.count());
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 6.16 创建无限流 iterate , generate
		Stream.iterate(0, n -> n + 2).limit(10).forEach(System.out::println);
		Stream.generate(Math::random).limit(10).forEach(System.out::println);
		// 6.17 joining
		String str1 = list1.stream().map(User::getName).collect(Collectors.joining());
		System.out.println(str1);
		String str2 = list1.stream().map(User::getName).collect(Collectors.joining(", "));
		System.out.println(str2);
		// 6.18 多级分组
		Map<Integer, Map<String, List<User>>> map3 = list1.stream().collect(Collectors.groupingBy(User::getAge, Collectors.groupingBy(User::getName)));
		System.out.println("多级分组: " + map3);
		// 6.19 按子组收集数据,还包括Collectors的maxBy,summingInt,summingDouble等方法
		Map<Integer, Long> map4 = list1.stream().collect(Collectors.groupingBy(User::getAge, Collectors.counting()));
		System.out.println("分组,counting: " + map4);
		Map<String, Optional<User>> map5 = list1.stream().collect(Collectors.groupingBy(User::getName, Collectors.maxBy(Comparator.comparingInt(User::getAge))));
		System.out.println("分组,maxby: " + map5);
		// 6.20 生成set
		Map<Integer, Set<User>> map6 = list1.stream().collect(Collectors.groupingBy(User::getAge, Collectors.toCollection(HashSet::new)));
		System.out.println("分组,set: " + map6);
		// 6.21 分区函数: 分区函数返回一个boolean值,即分组map的键类型是boolean,也即被分为两组-true一组,false一组
		Map<Boolean, List<User>> map7 = list1.stream().collect(Collectors.partitioningBy((User u7) -> u7.getAge() > 20));
		System.out.println("分区函数: " + map7);

		// 7. java8新的日期和时间api: LocalDate,LocalTime,Instant,Duration,Period
		// 7.1 LocalDate
		LocalDate date = LocalDate.of(2017, 3, 15);
		int year = date.getYear();
		Month month = date.getMonth();
		int day = date.getDayOfMonth();
		DayOfWeek dow = date.getDayOfWeek();
		int lengthOfMonth = date.lengthOfMonth();
		date = LocalDate.now();// 当前日期
		date = LocalDate.parse("2017-03-15");
		// 7.2 LocalTime
		LocalTime time = LocalTime.of(22, 27, 32);
		int hour = time.getHour();
		int minute = time.getMinute();
		int second = time.getSecond();
		time = LocalTime.parse("22:27:32");
		// 7.3 LocalDateTime
		LocalDateTime dt = LocalDateTime.of(2017, 3, 15, 22, 27, 32);
		dt = LocalDateTime.of(date, time);
		dt = date.atTime(22, 27, 32);
		dt = date.atTime(time);
		dt = time.atDate(date);
		// 7.4 Duration: 以秒和纳秒来衡量时间长短
		Duration d1 = Duration.between(LocalDateTime.now(), LocalDateTime.of(2017, 11, 6, 22, 27, 32));
		System.out.println("两个时间相差的秒数: " + d1.getSeconds());
		// 7.5 Period: 以年/月/日来衡量时间长短
		Period pd1 = Period.between(LocalDate.now(), LocalDate.of(2017, 11, 6));
		System.out.println("相差的年/月/日: " + pd1.getYears() + "/" + pd1.getMonths() + "/" + pd1.getDays());
		// 7.6 使用TemporalAdjuster
		LocalDate date2 = date.with(TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY));// 下周一
		date2 = date.with(TemporalAdjusters.lastDayOfMonth());// 本月最后一天

		// 8. 其它新加入的api
		// 8.1 emptyList
		List<User> list8 = Collections.emptyList();
		// 8.2 map新增的方法
		Map<Integer, String> map8 = new HashMap<>();
		System.out.println(map8.getOrDefault(1, "abc"));// 如果不存在键,则返回默认值abc

	}

	public static void setUserAge(User u, Predicate<User> p1, Consumer<User> c1) {
		if (p1.test(u)) {
			c1.accept(u);
		}
	}

}

class User {
	public String name;
	public Integer age;
	public boolean sex = true;

	public User() {
		super();
	}

	public User(String name) {
		super();
		this.name = name;
	}

	public User(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	public boolean isSex() {
		return sex;
	}

	public void setSex(boolean sex) {
		this.sex = sex;
	}

	@Override
	public String toString() {
		return "User [name=" + name + ", age=" + age + "]";
	}

}