JDK1.8新特性

JDK1.8新特性

1.Lambda表达式

Lambda是一个匿名函数,Lambda允许把函数作为一个方法的参数(函数作为参数传递到方法中),可以将Lambda表达式理解为是一段可以传递的代码。作为一种新语法,使得java语言表达能力得到提示,语言更加简洁,但也使得可读性变差。

1.1 lambda 表达式语法

lambda表达式语法:

主要通过->箭头操作符分割为两部分,左边为lambda函数参数,右边一部分lambda函数体

//1 
object -> expression
//2
(object1,object2) -> {}

1.2 Lambda表达式示例
public class LambdaTest {


   public static void main(String[] args) {
   	//1.匿名内部类转换为lambda
   	Runnable t1 = new Runnable() {
   		@Override
   		public void run() {
   			System.out.println("runnable-匿名内部类");
   		}
   	};
   	t1.run();
   	//Anonymous new Runnable() replaced with lambda
   	Runnable t2 = () -> System.out.println("runnable-lambda");
   	t2.run();
   	//————————————————————————————
   	//2.带有一个参数的lambda语法
   	//一个参数,括号也可以省略
   	//数据类型可以省略
   	Consumer<String> consumer = (s) -> System.out.println(s);
   	consumer = s -> System.out.println(s);
   	consumer.accept("带有一个参数的lambda语法");
   	//————————————————————————————
   	//3.两个参数语法
   	Comparator<Integer> comparator = (o1, o2) ->{
   		System.out.println("o1:" + o1);
   		System.out.println("o2:" + o2);
   		return (o1<o2)? o2 :(o1);
   	};
   	//当只有一行代码时,可以省略写法
   	Comparator<Integer> comparator2 = (o1, o2) ->(o1<o2)? o2 :(o1);
   	comparator.compare(123, 12);
   	comparator2.compare(123, 12);
   }
}

2.函数式接口

2.1 什么是函数式接口

只包含一个抽象方法的接口,在接口上添加 @FunctionalInterface 注解声明的为函数式接口,函数式接口可以隐式的转换为lambda表达式

/**
 * Success callback for a {@link ListenableFuture}.
 *
 * @author Sebastien Deleuze
 * @since 4.1
 * @param <T> the result type
 */
@FunctionalInterface
public interface SuccessCallback<T> {

	/**
	 * Called when the {@link ListenableFuture} completes with success.
	 * <p>Note that Exceptions raised by this method are ignored.
	 * @param result the result
	 */
	void onSuccess(@Nullable T result);

}
2.2 jdk1.8内置四大函数式接口
接口描述
Function<T,R>函数型接口
Consumer消费型接口
Supplier供给型接口
Predicate断言型接口
  • Function<T,R>:接收一个参数并产生一个结果
    /**
     * Represents a function that accepts one argument and produces a result.
     *
     * <p>This is a <a href="package-summary.html">functional interface</a>
     * whose functional method is {@link #apply(Object)}.
     *
     * @param <T> the type of the input to the function
     * @param <R> the type of the result of the function
     *
     * @since 1.8
     */
    @FunctionalInterface
    public interface Function<T, R> {
    
        /**
         * Applies this function to the given argument.
         *
         * @param t the function argument
         * @return the function result
         */
        R apply(T t);
    }
    
    

    示例:

        @org.junit.Test
        public  void testFunction() {
            //转为大写
            String str = testStr("fdasfd", a -> a.toUpperCase());
            System.out.println(str);
        }
    
        public String testStr(String str, Function<String, String> function){
            return function.apply(str);
        }
    
  • Consumer:接收一个参数,无任何返回值
    /**
     * Represents an operation that accepts a single input argument and returns no
     * result. Unlike most other functional interfaces, {@code Consumer} is expected
     * to operate via side-effects.
     *
     * <p>This is a <a href="package-summary.html">functional interface</a>
     * whose functional method is {@link #accept(Object)}.
     *
     * @param <T> the type of the input to the operation
     *
     * @since 1.8
     */
    @FunctionalInterface
    public interface Consumer<T> {
    
        /**
         * Performs this operation on the given argument.
         *
         * @param t the input argument
         */
        void accept(T t);
    

    示例:

    查看 **Iterable接口中的forEach()方法,还是通过Consumer**来调用for循环遍历

    /**
     * Implementing this interface allows an object to be the target of
     * the "for-each loop" statement. See
     * <strong>
     * <a href="{@docRoot}/../technotes/guides/language/foreach.html">For-each Loop</a>
     * </strong>
     *
     * @param <T> the type of elements returned by the iterator
     *
     * @since 1.5
     * @jls 14.14.2 The enhanced for statement
     */
    public interface Iterable<T> {
        /**
         * Returns an iterator over elements of type {@code T}.
         *
         * @return an Iterator.
         */
        Iterator<T> iterator();
    
        /**
         * Performs the given action for each element of the {@code Iterable}
         * until all elements have been processed or the action throws an
         * exception.  Unless otherwise specified by the implementing class,
         * actions are performed in the order of iteration (if an iteration order
         * is specified).  Exceptions thrown by the action are relayed to the
         * caller.
         *
         * @implSpec
         * <p>The default implementation behaves as if:
         * <pre>{@code
         *     for (T t : this)
         *         action.accept(t);
         * }</pre>
         *
         * @param action The action to be performed for each element
         * @throws NullPointerException if the specified action is null
         * @since 1.8
         */
        default void forEach(Consumer<? super T> action) {
            Objects.requireNonNull(action);
            for (T t : this) {
                action.accept(t);
            }
        }
    
  • Supplier: 供给型接口:没有输入参数,返回一个结果
    /**
     * Represents a supplier of results.
     *
     * <p>There is no requirement that a new or distinct result be returned each
     * time the supplier is invoked.
     *
     * <p>This is a <a href="package-summary.html">functional interface</a>
     * whose functional method is {@link #get()}.
     *
     * @param <T> the type of results supplied by this supplier
     *
     * @since 1.8
     */
    @FunctionalInterface
    public interface Supplier<T> {
    
        /**
         * Gets a result.
         *
         * @return a result
         */
        T get();
    }
    
    

    示例:

    @org.junit.Test
        public  void testRunSupplier() {
        testSupplier(()->"fdsafdsfds");
    }
    
    private void testSupplier(Supplier<String> supplier){
        System.out.println(supplier.get().toUpperCase());
    }
    
  • Predicate:断言型接口,接受一个输入参数,返回一个布尔结果
    /**
     * Represents a predicate (boolean-valued function) of one argument.
     *
     * <p>This is a <a href="package-summary.html">functional interface</a>
     * whose functional method is {@link #test(Object)}.
     *
     * @param <T> the type of the input to the predicate
     *
     * @since 1.8
     */
    @FunctionalInterface
    public interface Predicate<T> {
    
        /**
         * Evaluates this predicate on the given argument.
         *
         * @param t the input argument
         * @return {@code true} if the input argument matches the predicate,
         * otherwise {@code false}
         */
        boolean test(T t);
    
    

    示例:

     @org.junit.Test
        public  void testRunPredicate() {
            List<Integer> list = Arrays.asList(2,6,5);
         	//大于2的数
            List<Integer> integers = filterInt(list, num -> num > 2);
            System.out.println(integers);
        }
    
        public List<Integer> filterInt(List<Integer> nums ,Predicate<Integer> predicate){
            List<Integer> intList = new ArrayList<Integer>();
            for (Integer num : nums) {
                if(predicate.test(num)) intList.add(num);
            }
            return intList;
        }
    

3.默认方法

Java 8 增加了 **default**方法,用于实现接口的默认实现方法,且不需要类去实现接口中的方法。这样对于已经存在的接口修改接口中的方法不用去修改所有的实现,解决之前的缺陷。

3.1 语法
package java.lang;

import java.util.Iterator;
import java.util.Objects;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;

public interface Iterable<T> {
  
    Iterator<T> iterator();
  
    default void forEach(Consumer<? super T> action) {
        Objects.requireNonNull(action);
        for (T t : this) {
            action.accept(t);
        }
    }
    default Spliterator<T> spliterator() {
        return Spliterators.spliteratorUnknownSize(iterator(), 0);
    }
}

3.2 多个默认方法

默认接口1

public interface DeFaultInterfaceA {

	default void print(){
		System.out.println("默认方法A");
	}
}

默认接口2

public interface DeFaultInterfaceB {

	default void print(){
		System.out.println("默认方法B");
	}
}

实现方式1:

public class DefaultTestImpl  implements DeFaultInterfaceA,DeFaultInterfaceB{

	@Override
	public void print() {
		System.out.print("我是自己的实现方法");
	}
}

实现方式2:

public class DefaultTestImpl  implements DeFaultInterfaceA,DeFaultInterfaceB{

	@Override
	public void print() {
        //调用指定父类接口的方法
		DeFaultInterfaceA.super.print();
	}
}
3.3 静态默认方法
public interface DefaultStaticMethod {

	static void test(){
		System.out.println("接口的默认静态方法!");
	}
}

4.方法引用,构造引用,数组引用

4.1 方法引用

如果lambda方法体中的功能以及有方法提供了实现,那么可以使用方法引用,可以理解为Lambda 表达式的另一种表现形式。

方法引用所引用的方法的参数列表与返回值类型,需要与函数式接口中抽象方法的参数列表和返回值类型保持一致。

4.1.1语法:
  1. 对象的引用 :: 实例方法名
  2. 类名 :: 静态方法名
  3. 类名 :: 实例方法名
4.1.2示例:
@org.junit.Test
    public void testMethodRef(){

        Consumer<String> consumer = (s -> System.out.println(s.toUpperCase()));
        consumer.accept("abc,lambda表达式写法");
    	//对象的引用 :: 实例方法名
        consumer = this::toUpperCase;
        consumer.accept("aaa,方法引用写法");

    }
    private void toUpperCase(String str){
        System.out.println(str.toUpperCase());
    }
4.2 构造引用
4.2.1 语法
  • 类名 :: new
4.2.2 说明

可以把构造器中的引用赋值给定义的方法

4.2.3 注意事项

构造器的参数列表,需要与函数式接口中参数列表保持一致。

4.2.5 示例
@org.junit.Test
public void testConstructorRef() {
    //lambda写法
    Function<String, BigDecimal> function = (a) -> new BigDecimal(a);
    BigDecimal temp = function.apply("234");
    System.out.println(temp);
    //构造引用写法
    Function<String, BigDecimal> function2 = BigDecimal::new;
    BigDecimal temp2 = function2.apply("1321321");
    System.out.println(temp2);
}
4.3 数组引用
4.3.1 语法
  • 类型[] :: new
4.3.2 示例
	@org.junit.Test
	public void testArrayRef() {
		//lambda写法
		Function<Integer, BigDecimal[]> function = (a) -> new BigDecimal[a];
		BigDecimal[] tempArray = function.apply(4);
		System.out.println(tempArray.length);
		//数组引用写法
		Function<Integer, BigDecimal[]> function2 = BigDecimal[]::new;
		BigDecimal[] tempArray2 = function2.apply(3);
		System.out.println(tempArray2.length);
	}
4.3.3 注意事项

输入参数类型为数组长度

5.java Stream

5.1 什么是stream ?

Stream(流)是一个来自数据源的元素队列并支持聚合操作,帮助我们对更好地对数据进行集合操作。Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对Java集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。

这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选,排序,聚合等。

元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。

5.2 Stream特点
  • 元素是特定类型的对象,形成一个队列。Java的Stream不会存储元素 ,而是根据元素计算出需要的数据。
  • Stream 不会改变原对象,而是生成一个新的对象
  • 聚合操作:max,min 等
5.3 生成流
@org.junit.Test
	public void testCreateStream(){
		//通过Collection 系列集合提供的 stream() 或 parallelStream()
		List<String> list = new ArrayList<>();
//		list.parallelStream()
		Stream<String> stream = list.stream();

		//2.通过Arrays中的静态方法stream()获取数组流
		BigDecimal[] bigDecimals = new BigDecimal[10];
		Stream<BigDecimal> stream1 = Arrays.stream(bigDecimals);

		//3. 通过Stream类中的静态方法of()
		Stream<String> aaa = Stream.of("aaa", "bbb", "ccc");

		//4. 创建无限流
		//迭代
		Stream<Integer> iterate = Stream.iterate(1, (x) -> x + 3);
		iterate.limit(10).forEach((x)-> System.out.println(x));

		//生成
		Stream.generate(()->(int)(Math.random()*100)).limit(10).forEach(System.out::println);
	}
5.4 Stream中间操作

一个流可以后面跟随着0个或者多个中间操作,其目的是打开流,做出某种程度的数据过滤、去重、排序、映射、跳过等。然后返回一个新的流,交给下一个使用,仅仅是调用这个方法,没有真正开始遍历。

@org.junit.Test
	public void testStreamHandle(){
		//limit 截取指定数据量
		List<Integer> list = Stream.generate(() -> (int) (Math.random() * 100)).limit(30).collect(Collectors.toList());
		//filter 过滤出大于20的值
		list.stream().filter(a -> a > 20).forEach(System.out::print);
		System.out.println("------------------------------------------");
		list = Arrays.asList(1,2,21,2,2,2,3,3,1,2,43);
		//sorted排序 -- 正序
		System.out.println("sorted:");
		list.stream().sorted().forEach(System.out::print);
		System.out.println("------------------------------------------");
		//sorted排序 -- 倒序
		list.stream().sorted(Comparator.comparingInt(t-> (int) t).reversed()).forEach(item->{
			System.out.print(item+",");
		});;
		System.out.println("------------------------------------------");
		System.out.println("distinct:");
		//distinct 去重
		list.stream().distinct().forEach(item->{
			System.out.print(item+",");
		});;
		// skip跳过指定元素 返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补
		System.out.println("------------------------------------------");
		System.out.println("skip:");
		list.stream().skip(2).forEach(item->{
			System.out.print(item+",");
		});;
		//映射
		//map:接收Lambda,将元素转换成其他形式或提取信息,接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
		//flatMap: 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
		System.out.println("------------------------------------------");
		System.out.println("map:");
		list.stream().map(a->a + 2).forEach(item->{
			System.out.print(item+",");
		});
		System.out.println("------------------------------------------");
		System.out.println("flatMap:");
		list.stream().flatMap(this::flatMapTest).forEach(item->{
			System.out.print(item+",");
		});
	}

	/**
	 * 为每个int值添加一个比它大1的值
	 * @param a
	 * @return
	 */
	private Stream<Integer> flatMapTest(Integer a){
		return Stream.of(a,a+1);
	}
5.5 终止操作

一个终止操作,执行中间操作连,产生结果。

forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

6.Option 类

可以包含或者不包含非空值对象的容器,如果值存在 isPresent()将返回 true,并且 get()将返回值;作用就是用来代表值存不存在,原来使用null来表示,现在使用Option可以更好的表示,并且可以避免空指针异常

示例:

	@org.junit.Test
	public void testOption(){

		List<Integer> list = Arrays.asList(1, 2, 3, 3);
		//获取第一个等于3的值
		Optional<Integer> optionalInteger = list.stream().filter(o -> o.equals(3)).findFirst();
		if(optionalInteger.isPresent()){
			Integer result = optionalInteger.get();
			System.out.println(result);
		}

	}

7.新增日期类

java.util.Date:月份从0开始,对象不是最终的可以修改

java.util.Calendar:月份依然从0开始

格式化时间线程不安全,且两个都不为最终类,都可改变

解释
LocalDate本地日期(年月日)
LocalTime本地时间(时分秒)
LocalDateTime本地日期+时间
Instant时间戳,适合机器时间计算
Duration时间差
Period年、月、日差
ZoneOffset时区偏移量
ZonedDateTime带时区的日期时间
Clock时钟,获取其他地区时钟
DateTimeFormatter时间格式化
Temporal日期-时间获取值的字段
TemporalAdjusterTemporal对象转换,实现自定义
ChronoLocalDate日历系统接口

示例:

	@org.junit.Test
	public void testNewDate(){
		//获取当前日期
		LocalDate nowLocalDate = LocalDate.now();
		System.out.println(nowLocalDate);
		//获取当前时间
		LocalTime nowLocalTime = LocalTime.now();
		System.out.println(nowLocalTime);
		//日期时间
		LocalDateTime localDateTime = LocalDateTime.of(2022,12,17,8,11,12);
		System.out.println(localDateTime);
		System.out.println(localDateTime.getDayOfMonth());
		System.out.println(localDateTime.getHour());

		LocalDateTime nowLocalDateTime = LocalDateTime.now();
		Duration between = Duration.between(localDateTime, nowLocalDateTime);
		System.out.println("相差小时:"+between.toHours());
	}

输出结果:

2022-12-17
11:23:26.136
2022-12-17T08:11:12
17
8
相差小时:3
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值