Java 8语法学习

1. Lambda表达式

  1. 格式:

    • ->:lambda操作符 或箭头操作符
    • 左边:lambda形参列表,其实就是借口中的抽象方法的形参列表
    • 右边:malbda体,气死就是重写的抽象方法的方法体
  2. lambda表达式的使用

    总结:

    左边:lambda形参列表的参数类型可以省略(类型推断);如果lambda形参列表只有一个参数,其一对()也可以省略;

    右边:lambda体应该使用一对{}包裹;如果lambda体只有一条执行语句(可能是return语句),可以省略这一对{}和return关键字。

    • 无参,无返回值 Runnable r2 = () -> System.out.println("lambda表达式");
    • lambda需要一个参数,但是没有返回值 Consumer<String> con = (String s) -> System.out.println(s);
    • 数据类型可以省略,因为可由编译器推断得出,成为“类型推断” Consumer<String> con = (s) -> System.out.println(s);
    • lambda若只需要一个参数时,参数的小括号可以省略 Consumer<String> con = s -> System.out.println(s);
    • Lambda 需要两个以上的参数,多条执行语句,并且可以有返回值
    Comparator<Integer> comparator = (o1, o2) -> {
        System.out.println(o1);
        System.out.println(o2);
        return o1.compareTo(o2);
    };
    
    1. 当lambda体只有一条语句时,return与大括号都可以省略
  3. lambda表达式的本质:作为函数式接口的实例;

  4. 如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口;

  5. 所以以前用匿名实现类表示的现在都可以用lambda表达式来写。

  6. Java内置四大核心函数式接口

    • Consumer 消费型接口 对类型为T的对象应用操作,包含方法 void accept(T t)
    • Supplier 供给型接口 返回类型为T的对象,包含方法:T get()
    • Function<T, R> 函数型接口 对类型为T的对象应用操作,并返回结果,结果是R类型的对象。包含方法:R apply(T t)
    • Predicate 断定型接口 确定类型为T的对象是否满足某约束,并返回boolean值。包含方法: boolean test(T t)

2. 方法引用与构造器引用

方法引用

  1. 使用场景:当要传递给lambda体的操作,已经有实现的方法了,可以使用方法引用。

  2. 方法引用,本质上就是lambda表达式,而lambda表达式作为函数式接口的实例,所以方法引用也是函数式接口的实例。

  3. 使用格式:类(或对象)::方法名

  4. 具体分为以下情况:

    • 对象::非静态方法

      // 1. Consumer中的void accept(T t)  PrintStream中的println(T t)
      PrintStream ps = System.out;
      Consumer<String> con = ps::println;
      con.accept("beijing");
      // 2. Supplier中的T get()  Employee中的getName()
      Employee emp = new Employee();
      Supplier<String> sup = emp::getName;
      System.out.println(sup.get());
      
    • 类::静态方法

      // Comparator中的int compare(T t1, T t2); Integer中的int compare(T t1, T t2);
      Comparator<Integer> comp = Integer::compare;
      comp.compare(12, 24);
      
    • 类::非静态方法

      // Comparator中的int compare(T t1, T t2); String中的int t1.compareTo(t2);
      Comparator<String> comp = String::compareTo;
      comp.compare("abc", "abd");
      

构造器引用和数组引用

  1. 构造器引用:和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致 。抽象方法的返回值类型即位构造器所属的类的类型。
// Supplier<Employee> sup = () -> new Employee();
Supplier<Employee> sup = Employee::new;
  1. 数组引用:数组看作是一个特殊的类,和构造器引用类似。
// Function<Integer, String[]> func1 = length -> new String[length];
// func1.apply(2);
Funcion<Integer, String[]> func2 = String[] :: new;
func2.apply(2);

3. Stream API

  1. Stream 自己不会存储元素;
  2. Stream不会改变源对象。相反,他们会返回一个持有结果的新的Stream;
  3. Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
  1. 创建Stream:一个数据源
  2. 中间操作:对数据源的数据进行处理
  3. 终止操作:一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会在使用。

创建Stream

  1. 通过集合
default Stream<E> stream() {}  // 创建一个串行流
default Stream<E> parallelStream() {} // 创建一个并行流
  1. 通过数组
public static <T> stream(T[] array) {}  // 根据类型返回一个流
  1. 通过Stream的of()
public static<T> Stream<T> of(T... values) {}
  1. 创建无限流
// 迭代   遍历前10个偶数
public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {}
Stream.iterate(0, t->t+2).limit(10).forEach(System.out::println);

// 生成    遍历前10个随机数
public static<T> Stream<T> generate(Supplier<T> s) {} 
Stream.generate(Math::random).limit(10).forEach(System.out::println);

中间操作

  1. 筛选与切片
Stream<T> filter(Predicate<? super T> predicate); // 接收lambda,从流中排出元素
Stream<T> limit(long maxSize);  // 截断流
Stream<T> skip(long n); // 跳过元素
Stream<T> distinct(); // 筛选,通过流所生成元素的 hashCode()和equals() 去除重复的元素
  1. 映射

    1. map(Function f) 接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被引用到每个元素上,并将其映射成一个新的元素。
    //eg1:
    List<String> stringList = Arrays.asList("aa", "bb", "cc");
    stringList.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
    
    //eg2: 获取姓名长度大于3的名字
    List<Employee> employeeList = EmployeeData.getEmployee();
    employeeList.stream().map(Employee::getName).filter(name -> name.length()>2).forEach(System.out::println);
    
    1. flatMap(Function f) 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连成一个流。
    @Test
    public void test03() {
      List<String> stringList = Arrays.asList("aa", "bb", "cc");
      // flatMap  类似add addAll     
      Stream<Stream<Character>> streamStream = stringList.stream().map(StreamAPITest::fromStringToStream);
      streamStream.forEach(s->{
        s.forEach(System.out::println);
      });
      System.out.println("********");
      Stream<Character> characterStream = stringList.stream().flatMap(StreamAPITest::fromStringToStream);
      characterStream.forEach(System.out::println);
    
    }
    
    public static Stream<Character> fromStringToStream(String str) {
      ArrayList<Character> list = new ArrayList<>();
      for(Character c: str.toCharArray()) {
        list.add(c);
      }
      return list.stream();
    }
    
  2. 排序

    • sorted() 自然排序
    • sorted(Comparator com) 定制排序
    List<Employee> employees = EmployeeData.getEmployee();
    employees.stream().sorted((o1, o2) -> Integer.compare(o1.getAge(),o2.getAge())).forEach(System.out::println);
    employees.stream().sorted(Comparator.comparingInt(Employee::getAge)).forEach(System.out::println);
    

终止操作

  1. 匹配和查找
1. boolean allMatch(Predicate<? super T> predicate); 检查是否匹配所有元素。
//是否所有员工年龄大于18
boolean allMatch = employees.stream().allMatch(e -> e.getAge() > 18);
2. boolean anyMatch(Predicate<? super T> predicate); 检查是否匹配至少一个元素。
3. boolean noneMatch(Predicate<? super T> predicate); 检查是否没有匹配的元素,如果没有返回true
4. Optional<T> findFirst();  // 查找第一个元素
5. Optional<T> findAny();  // 查找任意一个元素 
// 串行流返回第一个;并行流会返回任意一个
Optional<Employee> any = employees.parallelStream().findAny();
6. long count()             返回流中元素的个数
7. Optional<T> max(Comparator<? super T> comparator);   返回流中的最大值
// 最高的钱数
Optional<Double> max = employees.stream().map(Employee::getMoney).max(Double::compareTo);
8. Optional<T> min(Comparator<? super T> comparator);   返回流中的最小值
// 最低的钱数的员工
Optional<Employee> min = employees.stream().min(Comparator.comparingDouble(Employee::getMoney));
9. void forEach(Consumer<? super T> action);
  1. 归约:可以将流中的元素反复结合起来,得到一个值。返回T
1. T reduce(T identity, BinaryOperator<T> accumulator);
// 计算1-10的自然数的和
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer integer = list.stream().reduce(0, Integer::sum);//第一个参数初始值

2. Optional<T> reduce(BinaryOperator<T> accumulator); // 求和
List<Employee> employees = EmployeeData.getEmployee();
Optional<Double> reduce = employees.stream().map(Employee::getMoney).reduce(Double::sum);
Optional<Double> reduce2 = employees.stream().map(Employee::getMoney).reduce((d1,d2) -> d1+d2);
System.out.println(reduce);
System.out.println(reduce2);
  1. 收集
// collect(Collector c) 将流转换为其他形式。接收一个Collector接口的实现,用于给Stream中元素做汇总的方法。
List<Employee> employees = EmployeeData.getEmployee();
List<Employee> list = employees.stream().filter(e -> e.getMoney() > 200).collect(Collectors.toList());
list.forEach(System.out::println);

4. Optional类

  1. 最常见的空指针异常,为了解决空指针异常;
创建Optional类对象的方法
  Optional.of(T t) 创建一个Optional实例,t必须非空;
  Optional.empty() 创建一个空的Optional实例;
  Optional.ofNullable(T t) t可以为null
  
判断Optional容器中是否包含对象
  boolean isPresent()    判断是否包含对象
  void ifPresent(Consumer<?super T> consumer)   如果有值,就执行Consumer接口的实现代码,并且该值回作为参数传递给他。
  
获取Optional容器的对象
  T get()  如果调用对象包含值,返回该值,否则抛异常
  T orElse(T other)  如果有值则将其返回,否则返回制定的other对象
  T orElseGet(Supplier<?extends T> other)  如果有值则将其返回,否则返回由Supplier接口实现提供的对象。
  T orElseThrow(Supplier<?extends T> exceptionSupplier)  如果有值则将其返回,否则跑出由Supplier接口实现提供的异常。
  1. 示例:
public String getGirlName(Boy boy) {
  return boy.getGirl().getName();
}
public String getGirlName1(Boy boy) {
  if (boy != null) {
    Girl girl = boy.getGirl();
    if (girl != null) {
      return girl.getName();
    }
  }
  return null;
}
public String getGirlName2(Boy boy) {
  Optional<Boy> boyOptional = Optional.ofNullable(boy);
  Boy boy1 = boyOptional.orElse(new Boy(new Girl("xiaoming")));

  Girl girl = boy1.getGirl();
  Optional<Girl> girlOptional = Optional.ofNullable(girl);
  Girl girl1 = girlOptional.orElse(new Girl("xiaohong"));
  return girl1.getName();
}
@Test
public void test02() {
  String girlName = getGirlName2(new Boy());
  System.out.println(girlName);
  String girlName1 = getGirlName2(null);
  System.out.println(girlName1);
}

5. 时间处理

包括:LocalDate、LocalTime、LocalDateTime

1. LocalDate

java中做时间处理时一般会采用java.util.Date,但是相比于Date来说,还有更好的选择 java.time.LocalDate。

LocalDate不包含时间,只是单纯的年月日

// 获取时间    返回值    意义     2020-01-21
getYear()  //   int    获取当前日期的年份   2020
getMonth() //   Month    获取当前日期的月份对象  month对象 JANUARY 数字从0开始
getMonthValue()  //  int    获取当前日期是第几月  1
getDayOfWeek()  //  DayOfWeek    表示该对象表示的日期是星期几  TUESDAY 数字从0开始
getDayOfMonth() //   int    表示该对象表示的日期是这个月第几天  21
getDayOfYear()  //  int    表示该对象表示的日期是今年第几天  21
// 如果传的值不正确,会报异常
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对象在时间上的大小,返回值如果为正,则当前对象时间较晚,other更小 
isBefore(ChronoLocalDate other)  //  boolean    比较当前对象日期是否在other对象日期之前  
isAfter(ChronoLocalDate other) //   boolean    比较当前对象日期是否在other对象日期之后  
isEqual(ChronoLocalDate other)  //  boolean    比较两个日期对象是否相等 
// 取当前日期:  
LocalDate today = LocalDate.now(); // -> 2020-01-02  
// 根据年月日取日期:  
LocalDate crischristmas = LocalDate.of(2019, 12, 25); // -> 2019-12-25  
// 根据字符串取:  
LocalDate endOfFeb = LocalDate.parse("2020-01-20"); // 严格按照ISO yyyy-MM-dd验证,01写成1都不行  
// 取本月第1天:  
LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth()); // 2020-01-01  
// 取本月第2天:  
LocalDate secondDayOfThisMonth = today.withDayOfMonth(2); // 2020-01-02  
// 取本月最后一天,再也不用计算是28,29,30还是31:  
LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth()); // 2020-01-31  
// 取下一天:  
LocalDate firstDayOf2018 = lastDayOfThisMonth.plusDays(1); // 变成了2020-02-01  
// 取2020年1月第一个周一
LocalDate firstMondayOf2020 = LocalDate.parse("2020-01-01").with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); // 2020-01-06

2. LocalTime

LocalTime只包含时间,获得当前时间:

// 构造时间
LocalTime now = LocalTime.now(); // 15:10:07.459
LocalTime zero = LocalTime.ofof(13, 55, 36); // 13:55:36  
LocalTime date = LocalTime.of(13, 55, 36, 123);//13:55:36.000000123   微毫 10^9
LocalTime mid = LocalTime.parse("13:55:36"); // 13:55:36
LocalTime time = LocalTime.parse("13:55:36.123");//13:55:36.123
// 访问时分秒,用法与LocalDate类似
getHour()  
getMinute()  
getSecond()  
getNano()
//  LocalTime类包含一系列方法,能帮你完成时间计算,用法与LocalDate类似
plusHours()  
plusMinutes()  
plusSeconds()  
plusNanos()  
minusHours()  
minusMinutes()  
minusSeconds()  
minusNanos()

3. LocalDateTime

// 构造时间
LocalDateTime nowDateTime = LocalDateTime.now(); //2020-01-21T15:07:39.980
LocalDateTime date = LocalDateTime.of(2020, 11, 26, 13, 55, 36, 123); //2020-11-26T13:55:36.000000123
LocalDateTime time = LocalDateTime.parse("2019-12-26T13:55:36.123"); //2019-12-26T13:55:36.123
// 访问日期时间,用法与LocalDate类似
getYear()  
getMonth()  
getDayOfMonth()  
getDayOfWeek()  
getDayOfYear()  
getHour()  
getMinute()  
getSecond()   
getNano()  
// LocalDateTime类包含一系列方法,能帮你完成时间计算,用法与LocalDate类似
plusYears()  
plusMonths()  
plusDays()  
plusHours()  
plusMinutes()  
plusSeconds()  
plusNanos()  
minusYears()  
minusMonths()  
minusDays()  
minusHours()  
minusMinutes()  
minusSeconds()  
minusNanos()  

4. mybatis中和mysql交互

  • 如果想要在JDBC中,使用Java8的日期LocalDate、LocalDateTime,则必须要求数据库驱动的版本不能低于4.2
  • LocalDate --> date
  • LocalTime --> time
  • LocalDateTime --> datetime

5. 相互转换

// localDateTime和string 互相转换
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        String timeToStr1 = dtf.format(now);
        System.out.println("localDateTime转string:" + timeToStr1);
        String timeToStr2 = now.format(dtf);
        System.out.println("localDateTime转string:" + timeToStr2);
        LocalDateTime strToTime = LocalDateTime.parse("2024-06-01 10:10", dtf);
        System.out.println("string转localDateTime转:" + strToTime);
        
// Date和string 互相转换
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        try {
            sdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
            Date strToDate = sdf.parse("2024-06-01 10:10");
            System.out.println("string转date:" + strToDate);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        String dateToStr = sdf.format(new Date());
        System.out.println("date转string:" + dateToStr);

// Date和localDateTime 互相转换
        Date nowDate = new Date();
        LocalDateTime localDateTime = nowDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        System.out.println("date转localDateTime:" +localDateTime);
        Date date = Date.from(now.atZone(ZoneId.systemDefault()).toInstant());
        System.out.println("localDateTime转date:" +date);
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值