Java8 新特性

Java8核心特性:Stream、Optional与Lambda表达式解析

Stream流

/**
		 * 创建流
		 */
		List<String> list = new ArrayList<>();
		Stream<String> stream = list.stream();// 顺序流
		Stream<String> parallelStream = list.parallelStream();// 并行流

		Stream<Integer> stream2 = Stream.iterate(0, x -> x + 2).limit(6);
		stream2.forEach(System.err::println);

		//将文件每一行内容转换成流
		BufferedReader reader =  new BufferedReader(new FileReader("D:\\test\\stream_text.txt"));
		Stream<String> lineStream = reader.lines();
		lineStream.forEach(System.out::println);
		
		
		/**
		 * 流的方法:
		 * 
		 * filter  
		 * limit(n)   获取n个元素
		 * skip(n)  跳过n个元素  与limit(n)可以实现分页
		 * distinct  过滤重复的元素   使用equls和hashCode
		 * 
		 */
		

Optional

		User user = new User("1", "name", "password");

		/**
		 * 	获取 Optional对象
		 * 
		 * 	static <T> Optional<T> empty()返回空的 Optional 实例
		 * 	static <T> Optional<T> of(T value) 返回一个指定非null值的Optional。
		 *  static <T> Optional<T> ofNullable(T value) 如果为非空,返回 Optional 描述的指定值,否则返回空的Optional
		 */
		Optional<User> empOptional = Optional.empty();
		Optional<User> ofoOptional = Optional.of(user);
		Optional<User> ofnullOptional = Optional.ofNullable(user);
		/**
		 * 	Optional<T> filter(Predicate<? super <T> predicate)
		 * 	 如果值存在,并且这个值匹配给定的 predicate(断言),返回一个Optional用以描述这个值,否则返回一个空的Optional。
		 */
		ofnullOptional.filter(u -> u.getId().equals("1"));
		/**
		 *	<U> Optional<U> flatMap(Function<? super T,Optional<U>> mapper) 
		 * 	如果值存在,返回基于Optional包含的映射方法的值,否则返回一个空的Optional
		 */
		ofnullOptional.flatMap(u -> Optional.ofNullable(u.getPassword()));
		/**
		 *  <U>Optional<U> map(Function<? super T,? extends U> mapper)
		 * 	如果有值,则对其执行调用映射函数得到返回值。如果返回值不为 null,则创建包含映射返回值的Optional作为map方法返回值,否则返回空Optional。
		 */
		ofnullOptional.map(u -> u.getPassword());
		
		/**
		 * T get() 如果在这个Optional中包含这个值,返回值,否则抛出异常:NoSuchElementException
		 */
		ofnullOptional.get();
		/**
		 * int hashCode() 返回存在值的哈希码,如果值不存在 返回 0。
		 */
		ofnullOptional.hashCode();
		
		/**
		 * void ifPresent(Consumer<? super T> consumer) 如果值存在则使用该值调用 consumer(消费函数),否则不做任何事情。
		 */
		ofnullOptional.ifPresent(u -> {
			System.out.println("逻辑代码");
		});
		
		/**
		 * boolean isPresent() 如果值存在则方法会返回true,否则返回 false。
		 */
		ofnullOptional.isPresent();
		/**
		 * T orElse(T other) 如果存在该值,返回值, 否则返回 other。
		 */
		ofnullOptional.orElse(new User("2","name","pwd"));
		/**
		 * T orElseGet(Supplier<? extends T> other) 如果存在该值,返回值, 否则触发 other,并返回 other 调用的结果。
		 */
		ofnullOptional.orElseGet(() ->{
			System.err.println("orElseGet");
			return new User("3","name","pwd");
		});
		/**
		 * <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) 
		 * 	如果存在该值,返回包含的值,否则抛出由 Supplier 继承的异常
		 */
		ofnullOptional.orElseThrow(() -> new NullPointerException("user为空"));
		
		
		//Demo
		ofnullOptional.filter(u -> u.getId().equals("1")).ifPresent(u -> {System.err.println(u.getPassword());});
		

Lambda 表达式

Lambda 表达式,也可称为闭包,Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。

语法

(parameters) -> expression
或
(parameters) ->{ statements; }

以下是lambda表达式的重要特征:

  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定表达式返回了一个数值。

Lambda实列

	@Test
	public void LambdaTest() {

		LambdaTest test = (a, b) -> a + b;
		System.err.println(test.sum(10, 15));

		methodTest((a, b) -> {
			return a * b;
		});
		
		Consumer consumer = msg -> System.err.println(msg);
		consumer.message("Hello Message");

	}

	interface LambdaTest {
		int sum(int a, int b);
	}

	interface Consumer {
		void message(String msg);
	}

	public void methodTest(LambdaTest test) {
		System.err.println(test.sum(10, 20));
	}

变量作用域

不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误

    @Test
	public void LambdaTest() {

		int num = 3;

		methodTest((a, b) -> {
            //编译错误
			num = 10;
			return a * num;
		});
		
	}
    
    public void methodTest(LambdaTest test) {
		System.err.println(test.sum(10, 20));
	}

	interface LambdaTest {
		int sum(int a, int b);
	}

方法引用

方法引用需要使用函数接口

	@FunctionalInterface
	public interface Supplier<T> {
		T get();
	}

	@Test
	void methodTest() {
		User user = create(User::new);
	}

	public static User create(Supplier<User> supplier) {
		return supplier.get();
	}

函数式接口

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

函数式接口可以被隐式转换为 lambda 表达式。

Lambda 表达式和方法引用(实际上也可认为是Lambda表达式)上。

常用函数接口

    @Test
	void functionIntface() {

		/**
		 * 接受一个输入参数,返回一个布尔值结果
		 */
		List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
		Predicate<Integer> predicate = n -> true;
		predicate = predicate.and(n -> n > 5).or(n -> n == 1);
		functionTest(list, predicate);

		/**
		 * 接受一个参数为类型T,返回值类型也为T。
		 */
		UnaryOperator<Integer> unaryOperator = n -> {
			return n + 100;
		};
		System.err.println(unaryOperator.apply(100));

		/**
		 * 代表了一个接受两个输入参数的操作,并且不返回任何结果
		 */

		BiConsumer<String, String> biConsumer = (n, n2) -> {
			System.err.println(n + n2);
		};

		biConsumer.accept("Hello", " BiConsumer");

		/**
		 * 代表了boolean值结果的提供方
		 */
		booleanSupplier(() -> false);
	}

	public void functionTest(List<Integer> list, Predicate<Integer> predicate) {

		for (Integer i : list) {
			if (predicate.test(i)) {
				System.err.println(i);
			}
		}

	}

	public void booleanSupplier(BooleanSupplier booleanSupplier) {

		System.err.println(booleanSupplier.getAsBoolean());
	}

默认方法

Java 8 新增了接口的默认方法。

简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法。

我们只需在方法名前面加个 default 关键字即可实现默认方法

为什么要有这个特性?

首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,目前的 java 8 之前的集合框架没有 foreach 方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了解决接口的修改与现有的实现不兼容的问题。

语法

public interface Vehicle {
   default void print(){
      System.out.println("我是一辆车!");
   }
}

日期时间 API

    @Test
	public void localDateTest() {

		LocalDateTime currentTime = LocalDateTime.now();
		System.err.println("当前时间:" + currentTime);
		System.err.println(currentTime.toLocalDate());
		System.err.println(currentTime.toLocalTime());

		Month month = currentTime.getMonth();
		int day = currentTime.getDayOfMonth();
		int seconds = currentTime.getSecond();

		System.err.println("月: " + month + ", 日: " + day + ", 秒: " + seconds);

		LocalDateTime date2 = currentTime.withDayOfMonth(10).withYear(2012);

		System.err.println(date2);
		// 解析字符串
		LocalTime date5 = LocalTime.parse("20:15:30");
		System.err.println("date5: " + date5);

		// 22 小时 15 分钟
		LocalTime date4 = LocalTime.of(22, 15);
		System.err.println("date4: " + date4);

		// 12 december 2014
		LocalDate date3 = LocalDate.of(2014, Month.DECEMBER, 12);
		System.err.println("date3: " + date3);

		
		System.out.println("========================带时区的时间======================");
		
		/**
		 * 获取当前时间日期
		 */
		ZonedDateTime date1 = ZonedDateTime.parse("2015-12-03T10:15:30+05:30[Asia/Shanghai]");
		System.err.println("date1: " + date1);

		ZoneId id = ZoneId.of("Europe/Paris");
		System.err.println("ZoneId: " + id);

		ZoneId currentZone = ZoneId.systemDefault();
		System.err.println("当期时区: " + currentZone);

	}

运行结果

当前时间:2022-08-15T17:32:45.081
2022-08-15
17:32:45.081
月: AUGUST, 日: 15, 秒: 45
2012-08-10T17:32:45.081
date5: 20:15:30
date4: 22:15
date3: 2014-12-12
date1: 2015-12-03T10:15:30+08:00[Asia/Shanghai]
ZoneId: Europe/Paris
当期时区: Asia/Shanghai

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值