Hz零基础学习JDK8~13新特性

1、JDK8之default关键字

可以在接口中添加实现方法。

场景:实现类所共有的一些逻辑代码,可以写到接口方法中。

default修饰的方式,可以被实现类重写。调用方式:实现类.default方式

static修饰的方法,不可以被实现类重写。调用方式:接口.静态方法


public interface Vegetables {

    void onName();

    default void onUnify(){
        System.out.println("我是蔬菜");
    }

    static void onStaticUnify(){
        System.out.println("我是静态蔬菜");
    }
}


public class VegetablesImpl implements Vegetables {
    @Override
    public void onName() {
        System.out.println("蔬菜实现类");
    }
    
    /** 可以重写default修饰的方法*/
}



public class Jdk8 {

    public static void main(String[] args) {
        Vegetables vegetables = new VegetablesImpl();
        vegetables.onName();
        vegetables.onUnify();

        Vegetables.onStaticUnify();
    }
}

2、JDK8新增Base64加解密API

不用引包,编解码效率高于sun.misc和Apache Commons Codec


    public static void main(String[] args) throws Exception{

        String str = "相信自己";
        Base64.Encoder encoder = Base64.getEncoder();
        Base64.Decoder decoder = Base64.getDecoder();

        String encodeToString = encoder.encodeToString(str.getBytes("utf-8"));
        System.out.println("加密后的字符串 "+encodeToString);
        
        String decoderStr = new String(decoder.decode(encodeToString), "utf-8");
        System.out.println("解密后的字符串 "+decoderStr);
    }

3、JDK8新增日期时间API

从Java 8开始,java.time包提供了新的日期和时间API,主要涉及的类型有:

本地日期和时间:LocalDateTime,LocalDate,LocalTime;
带时区的日期和时间:ZonedDateTime;
时刻:Instant;
时区:ZoneId,ZoneOffset;
时间间隔:Duration。

以及一套新的用于取代SimpleDateFormat的格式化类型DateTimeFormatter。

此外,新API修正了旧API不合理的常量设计:

  Month的范围用1~12表示1月到12月;
  Week的范围用1~7表示周一到周日。

 public class Main {
    public static void main(String[] args) {
        LocalDate d = LocalDate.now(); // 当前日期
        LocalTime t = LocalTime.now(); // 当前时间
        LocalDateTime dt = LocalDateTime.now(); // 当前日期和时间
        System.out.println(d); // 严格按照ISO 8601格式打印
        System.out.println(t); // 严格按照ISO 8601格式打印
        System.out.println(dt); // 严格按照ISO 8601格式打印
    }
}


LocalDateTime dt = LocalDateTime.now(); // 当前日期和时间
LocalDate d = dt.toLocalDate(); // 转换到当前日期
LocalTime t = dt.toLocalTime(); // 转换到当前时间

       
通过指定的日期和时间创建LocalDateTime可以通过of()方法:

// 指定日期和时间:
LocalDate d2 = LocalDate.of(2019, 11, 30); // 2019-11-30, 注意11=11月
LocalTime t2 = LocalTime.of(15, 16, 17); // 15:16:17
LocalDateTime dt2 = LocalDateTime.of(2019, 11, 30, 15, 16, 17);
LocalDateTime dt3 = LocalDateTime.of(d2, t2);

将字符串转换为LocalDateTime就可以传入标准格式

LocalDateTime dt = LocalDateTime.parse("2019-11-19T15:16:17");
LocalDate d = LocalDate.parse("2019-11-19");
LocalTime t = LocalTime.parse("15:16:17");

注意ISO 8601规定的日期和时间分隔符是T。标准格式如下:

日期:yyyy-MM-dd
时间:HH:mm:ss
带毫秒的时间:HH:mm:ss.SSS
日期和时间:yyyy-MM-dd'T'HH:mm:ss
带毫秒的日期和时间:yyyy-MM-dd'T'HH:mm:ss.SSS

DateTimeFormatter:自定义输出的格式。

public class Main {
    public static void main(String[] args) {
        // 自定义格式化:
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        System.out.println(dtf.format(LocalDateTime.now()));

        // 用自定义格式解析:
        LocalDateTime dt2 = LocalDateTime.parse("2019-11-30 15:16:17", dtf);
        System.out.println(dt2);
    }
}


LocalDateTime提供了对日期和时间进行加减的非常简单的链式调用:

public class Main {
    public static void main(String[] args) {
        LocalDateTime dt = LocalDateTime.of(2019, 10, 26, 20, 30, 59);
        System.out.println(dt);
        // 加5天减3小时:
        LocalDateTime dt2 = dt.plusDays(5).minusHours(3);
        System.out.println(dt2); // 2019-10-31T17:30:59
        // 减1月:
        LocalDateTime dt3 = dt2.minusMonths(1);
        System.out.println(dt3); // 2019-09-30T17:30:59
    }
}


注意到月份加减会自动调整日期,例如从2019-10-31减去1个月得到的结果是2019-09-30,因为9月没有31日。



调整是替换------

对日期和时间进行调整则使用withXxx()方法,例如:withHour(15)会把10:11:12变为15:11:12:

调整年:withYear()
调整月:withMonth()
调整日:withDayOfMonth()
调整时:withHour()
调整分:withMinute()
调整秒:withSecond()


public class Main {
    public static void main(String[] args) {
        LocalDateTime dt = LocalDateTime.of(2019, 10, 26, 20, 30, 59);
        System.out.println(dt);
        // 日期变为31日:
        LocalDateTime dt2 = dt.withDayOfMonth(31);
        System.out.println(dt2); // 2019-10-31T20:30:59
        // 月份变为9:
        LocalDateTime dt3 = dt2.withMonth(9);
        System.out.println(dt3); // 2019-09-30T20:30:59
    }
}

同样注意到调整月份时,会相应地调整日期,即把2019-10-31的月份调整为9时,日期也自动变为30。




要判断两个LocalDateTime的先后,可以使用isBefore()、isAfter()方法,对于LocalDate和LocalTime类似:

public class Main {
    public static void main(String[] args) {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime target = LocalDateTime.of(2019, 11, 19, 8, 15, 0);
        System.out.println(now.isBefore(target));
        System.out.println(LocalDate.now().isBefore(LocalDate.of(2019, 11, 19)));
        System.out.println(LocalTime.now().isAfter(LocalTime.parse("08:15:00")));
    }
}

LocalDateTime无法与时间戳进行转换,因为LocalDateTime没有时区,无法确定某一时刻。

--------------------------------------》52《----------------------------------------
ZonedDateTime:带时区的日期和时间。

public void tt(){
        //默认当前计算机时区
        ZonedDateTime now = ZonedDateTime.now();
        //指定伦敦时区
        ZonedDateTime london = ZonedDateTime.now(ZoneId.of("Europe/London"));
        System.out.println(now);
        System.out.println(london);
}


计算机存储的当前时间,本质上只是一个不断递增的整数。Java提供的System.currentTimeMillis()返回
的就是以毫秒表示的当前时间戳。
这个当前时间戳在java.time中以Instant类型表示,我们用Instant.now()获取当前时间戳,效果和
System.currentTimeMillis()类似:

public class Main {
    public static void main(String[] args) {
        Instant now = Instant.now();
        System.out.println(now.getEpochSecond()); // 秒
        System.out.println(now.toEpochMilli()); // 毫秒
    }
}

4、JDK8新增Optional类

Optional类用来解决对象空指针异常的问题的,提供针对空指针异常的操作的AIP。


Optional私有化构造方法,只能通过静态方法获取。


如果传入参数为空,将会抛出异常
Optional.of();

Integer integer = null;
Optional<Integer> optional = Optional.of(integer);

传入的参数可以为空,也可以不为空。但是get()方法获取时,如果为空抛出异常
Optional.ofNullable

Integer integer = null;
Optional<Integer> optional = Optional.ofNullable(integer);
Integer integer1 = optional.get();
System.out.println(integer1);


检测Optional是否为空,不为空可以通过get()方法,获取具体value
isPresent()

Integer integer = null;
Optional<Integer> optional = Optional.ofNullable(integer);
if(optional.isPresent()){
     System.out.println("不为空"+optional.get());
}else{
     System.out.println("为空");
}


如果Optional不为空,则返回Optional值,如果Optional为空,则返回orElse传入的参数
orElse()

Integer integer = null;
Integer integer1 = new Integer(22);

Integer integer2 = Optional.ofNullable(integer).orElse(integer1);
System.out.println(integer2); //2

5、JDK8新增Lambda表达式

函数式编程
JDK1.8之前不支持函数式编程,1.8以后支持。
函数式编程,是将一个函数(或称为方法)作为一个参数进行传递。


lambda表达式

注意:一个接口中只包含一个方法,则可以使用Lambda表达式,这样的接口成为"函数式接口"


声明该接口为函数式接口
@FunctionalInterface
public interface Belief {

   void onShow();

}


public class Jdk8 {

    public static void main(String[] args) throws Exception{
        onBelief(()-> System.out.println("我相信"));
    }

    public static void onBelief(Belief belief){
        belief.onShow();
    }
}



(参数) -> {方法体}

注意:
(1)如果参数为空,直接写() 如果只有一个参数,可以省略(),不需要写参数的类型。
(2)如果方法体只有一句代码,可以省略{}、省略return、省略分号。

6、JDK8提供Function接口

Lambda表达式必须先定义接口,才能使用。所有JDK8内置了许多函数式接口。


Function<T,R> 函数型接口,T入参 R返回值  只支持T一个入参


R apply(T t);


public static void main(String[] args) throws Exception {
     Function<String,String> function = str -> str;
     String apply = function.apply("你好我叫张三");
     System.out.println(apply);
}

7、JDK8提供BiFunction接口

@FunctionalInterface
public interface BiFunction<T, U, R> {}


R apply(T t, U u);  与Function相似 只不过可以接口2个参数




public static void main(String[] args) throws Exception {
      BiFunction<String,String,StringBuffer> biFunction = (a,b) -> {
          return new StringBuffer().append(a).append(b);
      };

      StringBuffer buffer = biFunction.apply("Hello", "World");
      System.out.println(buffer.toString());
}

8、JDK8提供Consumer接口

Consumer 消费型接口  有入参 无返回值


void accept(T t);


使用场景:用于打印、发送短信等消费动作



public static void main(String[] args) throws Exception {
   Consumer<String> consumer = str -> System.out.println(str);
   consumer.accept("打印输出");
}

9、JDK8提供Supplier接口

Supplier 供给型接口  无入参 有返回值

T get();

用途:返回创建对象


public class Jdk8 {

    public static void main(String[] args) throws Exception {
        Supplier<List<String>> supplier = () -> {
            return Arrays.asList("a", "b", "c");
        };
        List<String> list = supplier.get();
        list.forEach(str -> System.out.println(str));
    }
}

10、JDK8提供Predicate接口

Predicate 断言型接口  有入参 有返回值 但是返回是Boolean


boolean test(T t);

public static void main(String[] args) throws Exception {
   Predicate<Integer> predicate = i -> i.intValue() == 1;
   boolean b = predicate.test(2);
   System.out.println(b);
}

11、JDK8新增方法与构造器引用

调用方式或构造器引用  使用 :: 完成,接收参数为函数式接口。


调用(类,实例对象) :: 方法名;


静态方法调用 Class::方法名;
实例方法调用 对象::方法名;
构造方法调用 Class::new; 



public class Jdk8 {

    public static void main(String[] args) throws Exception {

        Function<String,Integer> function = Integer::parseInt;
        Integer integer = function.apply("123");
        System.out.println(integer);

        Supplier<MyUser> supplier0 = () -> {
         return new MyUser();   
        };
        //等价于上面写法
        Supplier<MyUser> supplier = MyUser::new;
        MyUser myUser = supplier.get();

    }


    static class MyUser{
        private String name;

        public MyUser() {

        }

        public String getName() {
            return name;
        }

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

12、JDK8新增Stream

stream 中文成为"流" 通常将集合转换为一种"流"元素队列,能够对集合中的每一个元素进行并行或串行的流
水线操作,可以进行排序、聚合、过滤等操作。

stream()串行流
parallelStream()并行流



List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> collect = list.stream().map(o -> {
     if (o % 2 == 0) {
          o++;
      }
      return o;
     }).collect(Collectors.toList());
System.out.println(collect);

13、Stream之Map函数

1.Map函数

Map接收Function<T,R>函数型接口,可以直接对流中的每一个元素就行操作。  

案例:通过map函数过滤返回铭感信息

@Data
public class Order {

    private String id;
    //敏感信息
    private String bankNum;

    private String name;
}

@Data
public class OrderDTO {
    private String id;

    private String name;
}



public static void main(String[] args) throws Exception {

  List<Order> orders = Arrays.asList(new Order("1", "2889898", "滑板"),
                                           new Order("2", "23232898", "面包"));
  List<Object> objects = orders.stream().map(obj -> {
       OrderDTO orderDTO = new OrderDTO(obj.getId(), obj.getName());
       return orderDTO;
  }).collect(Collectors.toList());
  System.out.println(objects);
}

14、Stream之filter函数

1.Filter函数

filter接收 Predicate 断言型接口,可以对数据进行过滤。



public static void main(String[] args) throws Exception {

    List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
    //只返回奇数
    List<Integer> integers = list.stream().filter(o -> o % 2 != 0).collect(Collectors.toList());
    System.out.println(integers);
}


15、Stream之limit函数

limit 截取返回指定数量


List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> collect = list.stream().limit(3).collect(Collectors.toList());
System.out.println(collect);

16、Stream之sorted函数

sorted 排序 自定义排序 默认升序


List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
//降序
List<Integer> collect1 = list.stream().sorted(Comparator.comparing(o -> 
o,Comparator.reverseOrder())).collect(Collectors.toList());
System.out.println(collect1);

17、Stream之allMatch函数

allMatch函数

检查是否匹配所有元素,只有全部匹配才返回true


List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
//判断集合中是否所有元素都大于2
boolean b = list.stream().allMatch(o -> o > 2);
System.out.println(b);   //false

18、Stream之anyMatch函数

anyMatch函数

检查是否匹配任意一个元素,匹配返回true  否则false


List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
//判断集合中任意一个元素是否大于2
boolean b = list.stream().anyMatch(o -> o > 2);
System.out.println(b); //true

19、Stream之Max函数

Max找出集合中最大值


List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
/**
 * 
* Comparator  也属于函数式接口
* int compare(T o1, T o2);
*/
Optional<Integer> max = list.stream().max((x, y) -> {
     return Integer.compare(x,y);
});
if(max.isPresent()){ System.out.println(max.get()); } //6

20、Stream之Min函数

min找出集合中最小值


List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
/**
 * 
* Comparator  也属于函数式接口
* int compare(T o1, T o2);
*/
Optional<Integer> max = list.stream().min((x, y) -> {
     return Integer.compare(x,y);
});
if(max.isPresent()){ System.out.println(max.get()); }

21、Stream之parallelStream

paralleStream用fork/join框架提供了并发执行能力。


底层原理:

线程池(ForkJoinPool)维护一个线程队列。

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
list.parallelStream().forEach(x ->{
    System.out.println("并发发送通知消息Id="+x);
});


paralleStream并行是否一定比Stream串行快?

不一定,数据量小的情况,可能Stream串行流更快,ForkJoin会消耗性能。


paralleStream多线程操作,会出现并发访问的问题。

22、Stream之reduce函数

reduce操作

聚合操作,根据一定的规则将stream中的元素进行计算后返回一个唯一的值。

@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> 


Stream.of创建一个流

常用方法一
Optional<T> reduce(BinaryOperator accumulator);

Optional<Integer> optional = Stream.of(1, 2, 3, 4, 5).reduce((x, y) -> x + y);
if(optional.isPresent()){
      System.out.println(optional.get()); //15
}

常用方法二

输入一个初始值 identity

T reduce(T identity,BinaryOperator accumulator);

Integer integer = Stream.of(1, 2, 3, 4, 5).reduce(100, (x, y) -> x + y);
System.out.println(integer); //115

23、foreach

forEach函数里面实现为

@FunctionalInterface
public interface Consumer<T> 消费型接口


Stream.of(1, 2, 3, 4, 5).forEach(System.out::println);



注意点:

使用forEach在消费型接口实现中,不能使用return、break、continue等关键跳过或者终止操作。

24、Collector

collect()

一个终端操作,用于对流中的数据进行归集作用,将流转变成具体的一个数据集合。


List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> list1 = list.stream().collect(Collectors.toList());
Set<Integer> set = list.stream().collect(Collectors.toSet());
LinkedHashSet<Integer> hashSet = list.stream().collect(Collectors.toCollection(LinkedHashSet::new));
TreeSet<Integer> treeSet = list.stream().collect(Collectors.toCollection(TreeSet::new));
Map<Integer, Integer> collect = list.stream().collect(Collectors.toMap(x -> x, x -> x));

25、joining函数

拼接函数  Collectors.joining


3种重载
Collectors.joining()
Collectors.joining("分隔符")
Collectors.joining("分隔符","头","尾")


String collect = Stream.of("张三", "李四", "王五", "马六").collect(Collectors.joining());
//张三李四王五马六
System.out.println(collect);
String collect1 = Stream.of("张三", "李四", "王五", "马六").collect(Collectors.joining("--"));
//张三--李四--王五--马六
System.out.println(collect1);
String collect2 = Stream.of("张三", "李四", "王五", "马六").collect(Collectors.joining("--", "开头", "结尾!"));
 //开头张三--李四--王五--马六结尾!
System.out.println(collect2);



26、partitioningBy函数

Collectors.partitioningBy分区,key是Boolean类型。

符合条件分成一组,不符合条件分成一组。



List<Integer> list = Arrays.asList(20, 60, 78, 92, 59);
//将大于60分的分成一组 小于60分的分成一组
Map<Boolean, List<Integer>> collect = list.stream().collect(Collectors.partitioningBy(x -> x >= 60));
//{false=[20, 59], true=[60, 78, 92]}
System.out.println(collect);

27、groupingBy函数

Collectors.groupingBy() 分组


public static void main(String[] args) throws Exception {
    List<Integer> list = Arrays.asList(20, 60,20, 78, 92, 59);
    // 分组
    Map<Integer, List<Integer>> collect = list.stream().collect(Collectors.groupingBy(x -> x));
    //{20=[20, 20], 59=[59], 92=[92], 60=[60], 78=[78]}
    System.out.println(collect);
}



public static void main(String[] args) throws Exception {
    List<Integer> list = Arrays.asList(20, 60,20, 78, 92, 59);
    // 分组 并统计个数
    Map<Integer, Long> collect = list.stream().collect(Collectors.groupingBy(x -> x, Collectors.counting()));
    //{20=2, 59=1, 92=1, 60=1, 78=1}
    System.out.println(collect);
}

28、summarizing函数

Collectors.summarizing类型()用来处理数据的统计分析的,比如总合、平均数等等


public static void main(String[] args) throws Exception {
        List<Integer> list = Arrays.asList(20, 60,20, 78, 92, 59);
        IntSummaryStatistics summaryStatistics = list.stream().collect(Collectors.summarizingInt(x -> x));
        System.out.println("平均数"+summaryStatistics.getAverage()); //System.out.println("平均数"+summaryStatistics.getAverage());
        System.out.println("总数"+summaryStatistics.getCount()); //总数6
        System.out.println("总合"+summaryStatistics.getSum()); //总合329
        System.out.println("最大值"+summaryStatistics.getMax()); //最大值92
        System.out.println("最小值"+summaryStatistics.getMin()); //最小值20
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值