java8新特性知识点(时间|Stream流)

135 阅读5分钟

一.时间

 1.获取当前日期(只能精确到年月日)
    String formatStr = "yyyy-MM-dd";
    LocalDate now = LocalDate.now();
    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(formatStr);               
    String nowFormat = now.format(dateTimeFormatter);
    System.out.println("格式化后的当前日期:"+nowFormat);
    结果: 格式化后的当前日期:2022-03-28
    
2.获取当前时间(可以精确到秒)
    String formatStr = "yyyy-MM-dd HH:mm:ss";
    LocalDateTime now = LocalDateTime.now();
    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(formatStr);
    String nowFormat = now.format(dateTimeFormatter);
    System.out.println("格式化后的当前日期:"+nowFormat);
    结果: 格式化后的当前日期:2022-03-28 10:15:51
    
3.操纵、解析和格式化日期
    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    LocalDateTime now = LocalDateTime.now();
    String nowFormat = now.format(dateTimeFormatter);
    System.out.println("格式化后的当前时间:"+nowFormat);
    //六小时前
    LocalDateTime minusTime = now.minusHours(6);
    String minusTimeFormat = minusTime.format(dateTimeFormatter);
    System.out.println("格式化后的6小时前的时间:"+minusTimeFormat);
    //六小时后
    LocalDateTime plusTime = now.plusHours(6);
    String plusTimeFormat = plusTime.format(dateTimeFormatter);
    System.out.println("格式化后的6小时后的时间:"+plusTimeFormat);
    //通过 isBefore或isAfter比较时间大小
    System.out.println("minusTime是否比now小: "+minusTime.isBefore(now));
    System.out.println("plusTime是否比now大: "+plusTime.isAfter(now));
    //指定时间和当前时间进行比较
    String str = "2022-03-27 14:41:06";
    LocalDateTime date = LocalDateTime.parse(str, dateTimeFormatter);
    System.out.println("date是否比now大: "+date.isAfter(now));
    //指定时间和当前时间pi
    String str1 = "2022-03-29 14:41:06";
    LocalDateTime date1 = LocalDateTime.parse(str1, dateTimeFormatter);
    System.out.println("date1是否比now大: "+date1.isAfter(now));

输出结果: 1648449069(1).png

备注:LocalDate类,LocalDateTime 类是线程安全,因为类被final类型。
1,写final域的重排序规则:JMM禁止编译器把final域的写重排序到构造函数初始化之外(之后)。
编译器会在final域的写之后,构造函数return之前,插入一个StoreStore内存屏障
2,读final域的重排序规则:在一个线程中,初次读对象引用与初次读该对象包含的final域,
JMM禁止重排序这2个操作。编译器会在读final域操作的前面插入一个LoadLoad屏障。

涉及的概念: 内存屏障(Memory Barrier)与内存栅栏(Memory Fence)是同一个概念
按照内存屏障的分类

  • 1.一类是强制读取主内存,强制刷新主内存的内存屏障,叫做Load屏障和Store屏障
    Store:将处理器缓存的数据刷新到内存中。
    Load:将内存存储的数据拷贝到处理器的缓存中。
  • 2.另外一类是禁止指令重排序的内存屏障,有四个分别叫做LoadLoad屏障、StoreStore屏障、LoadStore屏 障、StoreLoad屏障。
    如:store1指令 StoreStore屏障 store2指令:在store1指令和store2指令之间加上StoreStore屏障, 强制先 执行store1指令再执行store2指令;store1指令不能和store2指令进行重排序

二.Stream流

Stream(流)是一个来自数据源的元素队列并支持聚合操作

  • 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
  • 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
  • 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。

1. map()

官方: map:Returns a stream consisting of the results of applying the given function to the elements of this stream.
返回一个流,包含给定函数应用在流中每一个元素后的结果
(1)map 方法用于映射每个元素到对应的结果
例子:List numbers = Arrays.asList(1, 2, 3, 4, 5);
List squaresList = numbers.stream().map( i -> i*i).collect(Collectors.toList());
System.out.println(squaresList);
输出结果:[1, 4, 9, 16, 25]

(2)利用stream().map()提取List对象的某一列值
例:List nameList = studentList.stream().map(StudentInfo::getName).collect(Collectors.toList());

flatMap() 返回一个流,包含给定函数应用在流中每一个元素后的结果
官方:flatmap:Returns a stream consisting of the results of replacing each element of this stream with the contents of a mapped stream produced by applying the provided mapping function to each element.

用于将原有二维结构扁平化,

  1. Stream<String[]>
  2. Stream<Set<String>>
  3. Stream<List<String>>

以上这三类结构,通过 flatMap方法,可以将结果转化为 Stream<String>这种形式,方便之后的其他操作。

Stream map和flatmap的区别,请参考:
www.cnblogs.com/wangjing666…

2. reduce();

reduction 操作(也称为fold),通过反复的对一个输入序列的元素进行某种组合操作(如对数的集合求和、求最大值,或者将所有元素放入一个列表),最终将其组合为一个单一的概要信息
例子一:

    public static void main(String[] args) {
        ArrayList<Integer> newList = new ArrayList<>();
        ArrayList<Integer> accResult_s = Stream.of(1,2,3,4)
                .reduce(newList,
                        (acc, item) -> {
                            acc.add(item);
                            System.out.println("item: " + item);
                            System.out.println("acc+ : " + acc);
                            return acc;
                        }, (acc, item) -> null
                );
        System.out.println("accResult_s: " + accResult_s);
    }

结果:

1648458982(1).png

    1. 第一个参数:返回实例u,传递你要返回的U类型对象的初始化实例u
    2. 第二个参数:累加器accumulator,可以使用lambda表达式,声明你在u上累加你的数据来源t的逻辑,例如(u,t)->u.sum(t),此时lambda表达式的行参列表是返回实例u和遍历的集合元素t,函数体是在u上累加t
    3. 第三个参数:参数组合器combiner,接受lambda表达式。
    对于第三个函数参数,为什么没有执行,而且其参数必须为返回的数据类型?这是因为Stream是支持并发操作的,为了避免竞争,对于reduce线程都会有独立的result,combiner的作用在于合并每个线程的result得到最终结果。这也说明了了第三个函数参数的数据类型必须为返回数据类型了。
    

例子二:

Stream<Integer> integerStream = Stream.of(1,2,5,7,8,12,30); 
Integer sum = integerStream.reduce(0,(x,y)->x+y); 
System.out.println(sum);

3.groupingBy()

1.根据条件范围分组

public static void main(String[] args) {
    List<Dish> menu=new ArrayList<>();
    menu.add(new Dish("牛肉",300));
    menu.add(new Dish("猪肉",500));
    menu.add(new Dish("鱼肉",600));
    menu.add(new Dish("羊肉",800));
    Map<CaloricLevel, List<Dish>> dishesByCaloricLevel = menu.stream().collect(
            groupingBy(dish -> {
                if (dish.getCalories() <= 400) return CaloricLevel.DIET;
                else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
                else return CaloricLevel.FAT;
            } ));
    System.out.println(dishesByCaloricLevel);
}

结果是

1648461134(1).png

2.根据某个字段进行分组

public static void main(String[] args) {
    List<Dish> menu=new ArrayList<>();
    menu.add(new Dish("牛肉",300));
    menu.add(new Dish("猪肉",500));
    menu.add(new Dish("鱼肉",600));
    menu.add(new Dish("羊肉",800));
    menu.add(new Dish("",800));

    Map<String, List<Dish>> collect = menu.stream().collect(groupingBy(e -> {
        if (e.getName() == null || "".equals(e.getName())) {
            return "";
        }
        return e.getName();
    }));
    System.out.println(collect);

结果:

1648462363(1).png

4.此外还有:

  • filter 方法用于通过设置的条件过滤出元素

  • forEach Stream提供了新的方法 '' 来迭代流中的每个数据

  • limit 方法用于获取指定数量的流

  • sorted 方法用于对流进行排序

  • distinct 元素去重