Java8新特性

推荐文档

菜鸟教程https://www.runoob.com/java/java8-streams.html

Java8新特性https://www.runoob.com/java/java8-new-features.html

lamda表达式https://www.runoob.com/java/java8-lambda-expressions.html

base64 https://www.runoob.com/java/java8-base64.html

日期时间Api https://www.runoob.com/java/java8-datetime-api.html

stream https://www.runoob.com/java/java8-streams.html

日期时间APi

输出当前日期(年-月-日)

LocalDate today = LocalDate.now();
System.out.println("今天的日期:"+today);
一些LocalData.now()一些api
getYear()    int    获取当前日期的年份
getMonth()    Month    获取当前日期的月份对象
getMonthValue()    int    获取当前日期是第几月
getDayOfWeek()    DayOfWeek    表示该对象表示的日期是星期几
getDayOfMonth()    int    表示该对象表示的日期是这个月第几天
getDayOfYear()    int    表示该对象表示的日期是今年第几天
withYear(int year)    LocalDate    修改当前对象的年份
withMonth(int month)    LocalDate    修改当前对象的月份
withDayOfMonth(int dayOfMonth)    LocalDate    修改当前对象在当月的日期
isLeapYear()    boolean    是否是闰年
lengthOfMonth()    int    这个月有多少天
lengthOfYear()    int    该对象表示的年份有多少天(365或者366)
plusYears(long yearsToAdd)    LocalDate    当前对象增加指定的年份数
plusMonths(long monthsToAdd)    LocalDate    当前对象增加指定的月份数
plusWeeks(long weeksToAdd)    LocalDate    当前对象增加指定的周数
plusDays(long daysToAdd)    LocalDate    当前对象增加指定的天数
minusYears(long yearsToSubtract)    LocalDate    当前对象减去指定的年数
minusMonths(long monthsToSubtract)    LocalDate    当前对象减去注定的月数
minusWeeks(long weeksToSubtract)    LocalDate    当前对象减去指定的周数
minusDays(long daysToSubtract)    LocalDate    当前对象减去指定的天数
compareTo(ChronoLocalDate other)    int    比较当前对象和other对象在时间上的大小,返回值如果为正,则当前对象时间较晚,
isBefore(ChronoLocalDate other)    boolean    比较当前对象日期是否在other对象日期之前
isAfter(ChronoLocalDate other)    boolean    比较当前对象日期是否在other对象日期之后
isEqual(ChronoLocalDate other)    boolean    比较两个日期对象是否相等

TemporalAdjusters类中预定义实现

下面列举部分方法及其定义描述:

dayOfWeekInMonth() – 一周中的某一天,例如,三月中第二个星期二
firstDayOfMonth() – 当前月的第一天
firstDayOfNextMonth() – 下一个月的第一天
firstDayOfNextYear() – 下一年的第一天
firstDayOfYear() – 当年的第一天
lastDayOfMonth() – 当月的最后一天
nextOrSame() – 下一次或当天发生的一周中的某天

获取当月日期

LocalDate localDateStart = LocalDate.now()

localDateStart.getMonthValue() 获取当月

获取指定日期的上一个月

LocalDate localBeforeDate = localDateStart.minusMonths(1);

获取当月第一天

LocalDate localDateStart = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());

获取上月第一天

//当前月第一天
LocalDate localDateStart = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
LocalDate localBeforeDate = localDateStart.minusMonths(1);

获取上月最后一天

//当月第一天
LocalDate localDateStart = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
//上月第一天
LocalDate localBeforeDate = localDateStart.minusMonths(1);
//上月最后一天
LocalDate localDateEnd = localBeforeDate.with(TemporalAdjusters.lastDayOfMonth());

获取日期相差总天数

//相差总天数
//System.out.println("总相差的天数"+localStartDate.until(localEndDate, ChronoUnit.DAYS));

比较localStartDate和localEndDate相差的天数

LocalDateAPI

获取LocalDate

1.获取当前的日期 LocalDate
LocalDate now = LocalDate.now();

2.根据年月日的值获取 LocalDate
LocalDate.of(2016, 11, 30);

3.根据某年的第n天获取 LocalDate
LocalDate.ofYearDay(2016, 300)

4.从时间纪元(1970年1月1日)开始第n天(负数表示在时间纪元前n天)获取 LocalDate
LocalDate.ofEpochDay(365); 操作LocalDate

操作LocalDate

LocalDate.now().getYear(); // 年份  
LocalDate.now().getMonthValue(); // 月份(数值表示, 从1开始)  
LocalDate.now().getMonth(); // 月份(英文[enum]表示)  
LocalDate.now().getDayOfMonth(); // 日期(从1开始)  
LocalDate.now().getDayOfYear(): // 当天所在这一年的第几天(从1开始)  
LocalDate.now().getDayOfWeek(); // 星期几  
LocalDate.now().lengthOfYear(); // 当年的天数  
LocalDate.now().lengthOfMonth(); //当月的天数  
LocalDate.now().toEpochDay(); // 与时间纪元(1970年1月1日)相差的天数,负数表示在时间纪元之前多少天  

LocalDate运算

System.out.println("加法运算");  
System.out.println("当前:" + LocalDate.now());  
System.out.println("加1天:" + LocalDate.now().plusDays(1));  
System.out.println("加1周:" + LocalDate.now().plusWeeks(1));  
System.out.println("加1月:" + LocalDate.now().plusMonths(1));  
System.out.println("加1年:" + LocalDate.now().plusYears(1)); 
System.out.println("减法运算");  
System.out.println("当前:" + LocalDate.now());  
System.out.println("减1天:" + LocalDate.now().minusDays(1));  
System.out.println("减1周:" + LocalDate.now().minusWeeks(1));  
System.out.println("减1月:" + LocalDate.now().minusMonths(1));  
System.out.println("减1年:" + LocalDate.now().minusYears(1)); 
替换
    @Test
    public void test9(){
//        所有的数值必须合法;
//        如果当月当天是闰年2月29日,替换年份为非闰年,则会变成2月28日;
        System.out.println("当前:" + LocalDate.now()); 
        //替换日子为1日,以此类推(例今天为2022/9/30)替换后为(2022/9/1)
        System.out.println("替换日期为:" + LocalDate.now().withDayOfMonth(1));
        System.out.println("替换天数为:" + LocalDate.now().withDayOfYear(1));
        System.out.println("替换月份为:" + LocalDate.now().withMonth(1));
        System.out.println("替换年份为:" + LocalDate.now().withYear(1));
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tkXfZKXZ-1664525506322)(G:/typora/assets/image-20220704153111401-16645246694711.png)]

LocalDate比较

可以对两个 LocalDate 进行比较,可以判断一个日期是否在另一个日期之前或之后,或者判断两个日期是否是同年同月同日。
@Test
public void test10(){
        System.out.println("当天:" + LocalDate.now());
        System.out.println("是否在当天之前:" + LocalDate.now().minusDays(1).isBefore(LocalDate.now()));
        System.out.println("是否在当天之后:" + LocalDate.now().plusDays(1).isAfter(LocalDate.now()));
        System.out.println("是否在当天:" + LocalDate.now().isEqual(LocalDate.now()));
        System.out.println("今年是否是闰年:" + LocalDate.now().isLeapYear());
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sBb676Ml-1664525506322)(G:/typora/assets/image-20220704153216610-16645246694713.png)]

Lambda

lambda 表达式的语法格式如下:

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

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

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

Lambda 表达式的简单例子:

// 1. 不需要参数,返回值为 5  
() -> 5  
  
// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。

String first = "";
Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length());  //编译会出错 

Stream

stream概述

Stream 是在 Java8 新增的特性,普遍称其为流;它不是数据结构也不存放任何数据,其主要用于集合的逻辑处理

Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选、排序、聚合等。

stream特点

1.java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。
2.Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算  和    表达的高阶抽象。
3.Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
4.这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处   理, 比如筛选, 排序,聚合等。
5.元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal   operation)得到前面处理的结果

Stream图

image-20220708101446469

java8中的箭头表达式

java8中新增了一个操作符,“->”箭头表达式,也叫Lambda操作符。

stream的创建

1:通过 java.util.Collection.stream() 方法用集合创建流

List<String> list = Arrays.asList("x", "z", "y");
// 创建一个顺序流
Stream<String> stream = list.stream();
// 创建一个并行流
Stream<String> parallelStream = list.parallelStream();

2:使用java.util.Arrays.stream(T[] array)方法用数组创建流

int[] array={1,3,5,6,8};
IntStream stream = Arrays.stream(array);

3:Stream.of用于为给定元素**创建顺序流**。我们可以传递单个元素或多个元素。

      Stream<Integer> mystream = Stream.of(10, 12, 14, 16);
      mystream.forEach(e-> System.out.println(e));

Collectors toMap

//实体类 & 一个list集合
class Book {
    private int id;
    private String name;
    private int year;
//get set
}

List<Book> bookList = new ArrayList<>();
bookList.add(new Book(1,"Eyes blue", 1954));
bookList.add(new Book(1,"Eyes blue", 1999));
bookList.add(new Book(2,"Revenge", 2000));
bookList.add(new Book(3,"History", 1955));

可以使用toMap的重载方法

toMap的重载方法有4个

image-20220923214229856

----指定key为Id  Function.identity()Book对象本身
Map<Integer,Book> collect =books.stream().collect(Collectors.toMap(Book::getId, Function.identity()));
  • 当map的key存在重复的时候,直接映射会导致IllegalStateException异常
  • 需要在重复key的情况下,配置value的规则
----表示我们在key重复的时候,选择保留新的value还是旧的value
Map<Integer,Book> collect2 = as.stream().collect(Collectors.toMap(Book::getId, Function.identity(),(oldValue,newValue)-> newValue));

添加一个mapSupplier函数来返回一个ConcurrentHashMap:

ConcurrentHashMap<Integer,Book> collect55 = bookList.stream().collect(Collectors.toMap(Book::getId, Function.identity(),(oldValue,newValue)-> newValue,ConcurrentHashMap::new));

Collectors.groupingBy分组

System.out.println(bookList.stream().collect(Collectors.groupingBy(Book::getName)));

拼接流( Stream.concat(stream1,stream2))

        HashMap<String,String> nameMap = new HashMap<>();
        nameMap.put("xzy","徐子昀");
        nameMap.put("zcj","周成杰");
        nameMap.put("shihao","施浩");

        HashMap<String,Object> catMap = new HashMap<>();
        catMap.put("cat1","布偶猫");
        catMap.put("cat2","田园猫");
        catMap.put("cat3","英短");
        catMap.put("cat4","美短");


        //concat拼接流
        List<Map.Entry<String, ?>> collect = Stream.concat(nameMap.entrySet().stream(), 			   catMap.entrySet().stream()).collect(Collectors.toList());	
        System.out.println(collect);

streamparallelStream的区别

  • stream() − 为集合创建串行流。

  •     List<String> str = new ArrayList<>();
        str.add("1");
        str.add("2");
        str.add("3");
        
        /*单个线程执行任务*/
        str.stream().filter(e -> {
            System.out.println(Thread.currentThread().getName() + "\t过滤" + e);
            return Integer.parseInt(e) % 2 == 0 ? true : false;
        }).collect(Collectors.toList());
    

    image-20220708113057331

  • parallelStream() − 为集合创建并行流。

           str.parallelStream().filter(e -> {
                System.out.println(Thread.currentThread().getName() + "\t过滤" + e);
                return Integer.parseInt(e) % 2 == 0 ? true : false;
            }).collect(Collectors.toList());
    

    image-20220708113438605

image-20220708103303493

串行: 再在可能存在共享资源、线程安全等问题的时候使用

并行: 在无线程安全问题的前提下,并且单纯的数据处理的时候使用

遍历/匹配(foreach/find/match)

Stream也是支持类似集合的遍历和匹配元素的,只是Stream中的元素是以Optional类型存在的。Stream的遍历、匹配非常简单

// import已省略,请自行添加,后面代码亦是

public class StreamTest {
	public static void main(String[] args) {
        //数组转List的静态方法
        List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);

        // 遍历输出符合条件的元素
        list.stream().filter(x -> x > 6).forEach(System.out::println);
        // 匹配第一个
        Optional<Integer> findFirst = list.stream().filter(x -> x > 6).findFirst();
        // 匹配任意(适用于并行流)
        Optional<Integer> findAny = list.parallelStream().filter(x -> x > 6).findAny();
        // 是否包含符合特定条件的元素
        boolean anyMatch = list.stream().anyMatch(x -> x > 6);
        System.out.println("匹配第一个值:" + findFirst.get());
        System.out.println("匹配任意一个值:" + findAny.get());
        System.out.println("是否存在大于6的值:" + anyMatch);
    }
}

筛选(filter)

filter() 筛选,是按照一定的规则校验流中的元素,将符合条件的元素筛选出来

.collect()将流再转换成list返回,便于输出

image-20220708103522024

/
** filter()
* 把符合要求的元素筛选出来
*/
List<Person> collect = list.stream().filter(item -> item.getAge() > 20).collect(Collectors.toList());
#这里我们筛选对象年龄大于20的并输出
System.out.println(collect);

去重(distinct)

/** distinct()
* 去除重复元素,重写了equals和hashcode方法可以去除对象
*/
List<Person> distinct = list.stream().distinct().collect(Collectors.toList());
 System.out.println(distinct);

获取流前N个元素(limit)

/** limit()
 * limit获取流前n个元素
 */
List<Person> limit = list.stream().limit(3).collect(Collectors.toList());
System.out.println(limit);

获取除了流前N个元素(skip)

/** skip()
 * skip获取流除了前n个元素,相当于limit()取反
 */
List<Person> skip = list.stream().skip(3).collect(Collectors.toList());
System.out.println(skip);

映射(map/flatMap)

映射,可以将一个流的元素按照一定的映射规则映射到另一个流中。分为mapflatMap

  • map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

  • flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

  • // 解析:flatMap
    // (1) [a,b,c],[b,c],…,[e,f]
    // (2) [a,b,c,…,e,f] 扁平化操作

  • // 解析:map
    // [a,b,c],[b,c],...,[e,f]
    

    案例一:英文字符串数组的元素全部改为大写

    List<String> string = Arrays.asList("abc","bzovo");
    List<String> collect2 = string.stream().map(str -> str.toUpperCase()).collect(Collectors.toList());
    System.out.println(collect2);
    

    案例二:将员工的薪资全部增加1000。

    List<Double> collect1 = list.stream().map(person -> person.getSalary() + 400).collect(Collectors.toList());
    System.out.println("第一位的薪水为"+collect1.get(0));
    System.out.println("第二位的薪水为"+collect1.get(1));
    System.out.println("第三位的薪水为"+collect1.get(2));
    

    image-20220708110133873

    image-20220708110107173

聚合(max/min/count)

maxmincount这些字眼你一定不陌生,没错,在mysql中我们常用它们进行数据统计。Java stream中也引入了这些概念和用法,极大地方便了我们对集合、数组的数据统计工作。

案例一:获取String集合中最长的元素。

List<String> list2 = Arrays.asList("adnm", "admmt", "pot", "xbangd", "weoujgsd");
Optional<String> max = list2.stream().max(Comparator.comparing(String::length));
System.out.println("最长的字符串:" + max.get());

案例二:获取Integer集合中的最大值。

		List<Integer> list = Arrays.asList(7, 6, 9, 4, 11, 6);

		// 自然排序
		Optional<Integer> max = list.stream().max(Integer::compareTo);
		// 自定义排序
		Optional<Integer> max2 = list.stream().max(new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				return o1.compareTo(o2);
			}
		});
		System.out.println("自然排序的最大值:" + max.get());
		System.out.println("自定义排序的最大值:" + max2.get());

归约(reduce)

归约,也称缩减,顾名思义,是把一个流缩减成一个值,能实现对集合求和、求乘积和求最值操作

public class StreamTest {
	public static void main(String[] args) {
		List<Integer> list = Arrays.asList(1, 3, 2, 8, 11, 4);
		// 求和方式1
		Optional<Integer> sum = list.stream().reduce((x, y) -> x + y);
		// 求和方式2
		Optional<Integer> sum2 = list.stream().reduce(Integer::sum);
		// 求和方式3
		Integer sum3 = list.stream().reduce(0, Integer::sum);
		
		// 求乘积
		Optional<Integer> product = list.stream().reduce((x, y) -> x * y);

		// 求最大值方式1
		Optional<Integer> max = list.stream().reduce((x, y) -> x > y ? x : y);
		// 求最大值写法2
		Integer max2 = list.stream().reduce(1, Integer::max);

		System.out.println("list求和:" + sum.get() + "," + sum2.get() + "," + sum3);
		System.out.println("list求积:" + product.get());
		System.out.println("list求和:" + max.get() + "," + max2);
	}
}

收集(collect)

collect,收集,可以说是内容最繁多、功能最丰富的部分了。从字面上去理解,就是把一个流收集起来,最终可以是收集成一个值也可以收集成一个新的集合。

collect主要依赖java.util.stream.Collectors类内置的静态方法。

List<String> string = Arrays.asList("abc","bzovo");
List<String> collect2 = string.stream().map(str -> str.toUpperCase()).collect(Collectors.toList());

统计(count/averaging)

Collectors提供了一系列用于数据统计的静态方法:

计数:count
平均值:averagingInt、averagingLong、averagingDouble
最值:maxBy、minBy
求和:summingInt、summingLong、summingDouble
统计以上所有:summarizingInt、summarizingLong、summarizingDouble

public class StreamTest {
	public static void main(String[] args) {
		List<Person> personList = new ArrayList<Person>();
		personList.add(new Person("Tom", 8900, 23, "male", "New York"));
		personList.add(new Person("Jack", 7000, 25, "male", "Washington"));
		personList.add(new Person("Lily", 7800, 21, "female", "Washington"));

		// 求总数
		Long count = personList.stream().collect(Collectors.counting());
		// 求平均工资
		Double average = personList.stream().collect(Collectors.averagingDouble(Person::getSalary));
		// 求最高工资
		Optional<Integer> max = personList.stream().map(Person::getSalary).collect(Collectors.maxBy(Integer::compare));
		// 求工资之和
		Integer sum = personList.stream().collect(Collectors.summingInt(Person::getSalary));
		// 一次性统计所有信息
		DoubleSummaryStatistics collect = personList.stream().collect(Collectors.summarizingDouble(Person::getSalary));

		System.out.println("员工总数:" + count);
		System.out.println("员工平均工资:" + average);
		System.out.println("员工工资总和:" + sum);
		System.out.println("员工工资所有统计:" + collect);
	}
}

排序(sorted)

sorted,中间操作。有两种排序:

  • sorted():自然排序,流中元素需实现Comparable接口
  • sorted(Comparator com):Comparator排序器自定义排序
//按照id升序
bookList.stream().sorted((o1,o2)->o1.getId()-o2.getId()).collect(Collectors.toList()).forEach(System.out::println);
//按照id降序
bookList.stream().sorted((o1,o2)->o2.getId()-o1.getId()).collect(Collectors.toList()).forEach(System.out::println);
public class StreamTest {
	public static void main(String[] args) {
		List<Person> personList = new ArrayList<Person>();

		personList.add(new Person("Sherry", 9000, 24, "female", "New York"));
		personList.add(new Person("Tom", 8900, 22, "male", "Washington"));
		personList.add(new Person("Jack", 9000, 25, "male", "Washington"));
		personList.add(new Person("Lily", 8800, 26, "male", "New York"));
		personList.add(new Person("Alisa", 9000, 26, "female", "New York"));

		// 按工资升序排序(自然排序)
		List<String> newList = personList.stream().sorted(Comparator.comparing(Person::getSalary)).map(Person::getName)
				.collect(Collectors.toList());
		// 按工资倒序排序
		List<String> newList2 = personList.stream().sorted(Comparator.comparing(Person::getSalary).reversed())
				.map(Person::getName).collect(Collectors.toList());
		// 先按工资再按年龄升序排序
		List<String> newList3 = personList.stream()
				.sorted(Comparator.comparing(Person::getSalary).thenComparing(Person::getAge)).map(Person::getName)
				.collect(Collectors.toList());
		// 先按工资再按年龄自定义排序(降序)
		List<String> newList4 = personList.stream().sorted((p1, p2) -> {
			if (p1.getSalary() == p2.getSalary()) {
				return p2.getAge() - p1.getAge();
			} else {
				return p2.getSalary() - p1.getSalary();
			}
		}).map(Person::getName).collect(Collectors.toList());

		System.out.println("按工资升序排序:" + newList);
		System.out.println("按工资降序排序:" + newList2);
		System.out.println("先按工资再按年龄升序排序:" + newList3);
		System.out.println("先按工资再按年龄自定义降序排序:" + newList4);
	}
}

Optional 类

Optional 类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。

Optional 类的引入很好的解决空指针异常。

日期时间Api

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值