Java8新特性

2018-05-12  本文已影响0人  影风扬

1.Lamda表达式

Lambda表达式的作用主要是用来简化接口的创建,使用Lambda表达式接口必须是函数式接口

@Test
public void testLambda() {
    new Thread(() -> {
        for (int i = 0; i < 10; i++) {
            log.info(" {} ", i);
        }
    }).start();
}

2.函数式接口

函数式接口只能有一个抽象方法,使用@FunctionalInterface注解可以检查是否是函数式接口

@FunctionalInterface
interface MyFunc<T> {
    T getValue(T t);
}

Consumner<T> : 消费型接口

void accept(T t);

用途:对类型为T的对象应用操作,包含方法:void accept(T t);

@Test
public void testConsume() {
    pay(1000, money -> System.out.println("购物消费了" + money + "元"));
}

private void pay(int money, Consumer<Integer> consumer) {
    consumer.accept(money);
}

Supplier<T> :供给型接口

T get();

用途:返回类型为T的对象,包含方法:T get();

@Test
public void testSupplier() {
    List<Integer> list = getNumList(10, () -> (int)(Math.random() * 100));
    for (int num : list) {
        System.out.println("supplier" + num);
    }
}

private List<Integer> getNumList(int num, Supplier<Integer> supplier) {
    List<Integer> list = new ArrayList<>();

    for (int i = 0; i < num; i++) {
        list.add(supplier.get());
    }

    return list;
}

Function<T , R>:函数式接口

R apply(T t);

用途:对类型为T的对象应用操作,并返回结果,结果是R类型的对象,包含方法:R apply(T t);

@Test
public void testFunction() {
    String name = "Jack Yang";
    System.out.print(strHandler(name, String::toLowerCase));
}
private String strHandler(String str, Function<String, String> func) {
    return func.apply(str);
}

Predicate<T>:断言型接口

boolean test(T t);

用途:确定类型为T的对象是否满足某约束,并返回boolean值,包含方法:boolean test(T t);

@Test
public void testPredicate() {
    List<String> list = filterStr(
        Arrays.asList("jackyang", "jackie", "jordan", "ronaldo", "figo", "zidane"),
        s -> s.length() >= 6
    );
    for (String name : list) {
        System.out.println(name);
    }
}

private List<String> filterStr(List<String> list, Predicate<String> predicate) {
    List<String> handleList = new ArrayList<>();
    for(String str : list) {
        if(predicate.test(str)) {
            handleList.add(str);
        }
    }
    return handleList;
}

其他函数式接口(http://www.runoob.com/java/java8-functional-interfaces.html)

3.方法引用

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

若Lambda 的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式: ClassName::MethodName

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

三种语法格式

4.Stream API

集合讲的是数据,流讲的是计算!
Stream流的操作三个步骤
创建Stream流

default Stream<E> stream() : 返回一个顺序流

default Stream<E> parallelStream() : 返回一个并行流

static <T> Stream<T> stream(T[] array): 返回一个流

public static<T> Stream<T> of(T... values) : 返回一个流

迭代 public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)

生成 public static<T> Stream<T> generate(Supplier<T> s)

@Slf4j
public class StreamTest extends AdminApiApplicationTests {
    @Data
    class Student {
        private String name;
        private Integer age;

        public Student(String name, Integer age) {
            this.name = name;
            this.age = age;
        }
    }

    @Test
    public void testStreamCreate() {
        System.out.println("-----------集合创建流-----------");
        Arrays.asList("jackyang", "", "jordan", "helloworld", "hellokitty").stream().filter(s -> s.length() > 8).forEach(System.out::println);

        System.out.println("-----------数据创建流-----------");
        Student[] students = new Student[]{
                new Student("jackyang", 30),
                new Student("jordan", 40),
                new Student("kitty", 18)
        };
        Arrays.stream(students).filter(student -> student.age > 20).forEach(System.out::println);

        System.out.println("-----------值创建流-----------");
        Stream.of(students).filter(student -> student.age < 20).forEach(System.out::println);

        System.out.println("-----------创建无限流-----------");
        Stream.iterate(5, s -> s + 2).limit(10).forEach(System.out::println);
        Stream.generate(() -> (int)(Math.random() * 100)).limit(10).forEach(System.out::println);
    }
}
中间操作

中间操作不会执行任何的操作,而是在终止操作时一次性全部处理,称为“惰性求值”

终止操作

终止操作会从流的流水线生成结果,其结果可以是任何不是流的值,例如:List、Integer,甚至是 void

匹配

查找

遍历

规约

收集

用于给Stream中元素做汇总的方法

toList
List<T>
把流中元素收集到List
List<Employee> emps = list.stream().collect(Collectors.toList());

Set<T>
把流中元素收集到Set
Set<Employee> emps = list.stream().collect(Collectors.toSet());
 
toCollection
Collection<T>
把流中元素收集到创建的集合
Collection<Employee>emps =list.stream().collect(Collectors.toCollection(ArrayList::new));
 
counting
Long
计算流中元素的个数
long count = list.stream().collect(Collectors.counting());
 
summingInt
Integer
对流中元素的整数属性求和
int total = list.stream().collect(Collectors.summingInt(Employee::getSalary));
 
averagingInt
Double
计算流中元素Integer属性的平均 值
double avg = list.stream().collect(Collectors.averagingInt(Employee::getSalary));
 
summarizingInt
IntSummaryStatistics
收集流中Integer属性的统计值。 如:平均值
IntSummaryStatistics iss = list.stream().collect(Collectors.summarizingInt(Employee::getSalary));

joining
String
连接流中每个字符串
String str = list.stream().map(Employee::getName).collect(Collectors.joining());
 
maxBy
Optional<T>
根据比较器选择最大值
Optional<Emp>max = list.stream().collect(Collectors.maxBy(comparingInt(Employee::getSalary)));
 
minBy
Optional<T>
根据比较器选择最小值
Optional<Emp> min = list.stream().collect(Collectors.minBy(comparingInt(Employee::getSalary)));

reducing
归约产生的类型
从一个作为累加器的初始值开始,利用BinaryOperator与 流中元素逐个结合,从而归约成单个值
int total = list.stream().collect(Collectors.reducing(0, Employee::getSalar, Integer::sum));

collectingAndThen
转换函数返回的类型
包裹另一个收集器,对其结 果转换函数
int how = list.stream().collect(Collectors.collectingAndThen(Collectors.toList(), List::size));
    
groupingBy
Map<K, List<T>>
根据某属性值对流分组,属 性为K,结果为V
Map<Emp.Status, List<Emp>> map= list.stream() .collect(Collectors.groupingBy(Employee::getStatus));

partitioningBy
Map<Boolean, List<T>>
根据true或false进行分区
Map<Boolean,List<Emp>> vd = list.stream().collect(Collectors.partitioningBy(Employee::getManage));

5.并行流与串行流

并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流

可以使用parallel() 与 sequential() 在并行流与串行流之间进行切换

Fork/Join框架: 就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行join汇总.
采用 “工作窃取”模式(work-stealing): 当执行新的任务时它可以将其拆分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中

6.新时间日期 API

now() 静态方法,根据当前时间创建对象
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now(); LocalDateTime localDateTime = LocalDateTime.now();

of() 静态方法,根据指定日期/时间创建 对象
LocalDate localDate = LocalDate.of(2016, 10, 26); 
LocalTime localTime = LocalTime.of(02, 22, 56); 
LocalDateTime localDateTime = LocalDateTime.of(2016, 10, 26, 12, 10, 55);

plusDays, plusWeeks, plusMonths, plusYears 向当前 LocalDate 对象添加几天、 几周、几个月、几年

minusDays, minusWeeks, minusMonths, minusYears 从当前 LocalDate 对象减去几天、 几周、几个月、几年

plus, minus 添加或减少一个 Duration 或 Period

withDayOfMonth, withDayOfYear, withMonth, withYear 将月份天数、年份天数、月份、年 份修改为指定的值并返回新的 LocalDate 对象

getDayOfMonth 获得月份天数(1-31)

getDayOfYear 获得年份天数(1-366)

getDayOfWeek 获得星期几(返回一个 DayOfWeek 枚举值)

getMonth 获得月份, 返回一个 Month 枚举值

getMonthValue 获得月份(1-12)

getYear 获得年份

until 获得两个日期之间的 Period 对象, 或者指定 ChronoUnits 的数字

isBefore, isAfter 比较两个 LocalDate

isLeapYear 判断是否是闰年

Duration:用于计算两个时间间隔

Period:用于计算两个日期间隔

@Test
public void testDateFormat() {
    LocalDateTime local = LocalDateTime.now();
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    System.out.println(formatter.format(local));
}

@Test
public void testDateFormat() {
    LocalDateTime local = LocalDateTime.now();
    String dateTime = local.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"));
    System.out.println(dateTime);
}

@Test
public void testDateFormat() {
    DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    String strDate = "2018年05月12日 14:31:33";
    LocalDateTime ldt = LocalDateTime.now();
    LocalDateTime newDate = ldt.parse(strDate, dateTimeFormatter);
    System.out.println(newDate);
}

7.接口中默认方法与静态方法

接口默认方法的类优先原则

若一个接口中定义了一个默认方法,而另外一个父类或接口中又定义了一个同名的方法时选择父类中的方法

如果一个父类提供了具体的实现,那么接口中具有相同名称和参数的默认方法会被忽略

接口冲突:

如果一个父接口提供一个默认方法,而另一个接口也提供了一个具有相同名称和参数列表的方法(不管方法是否是默认方法),那么必须覆盖该方法来解决冲突

8.Optional类

常用方法:
Optional.of(T t) : 创建一个 Optional 实例

Optional.empty() : 创建一个空的 Optional 实例

Optional.ofNullable(T t):若 t 不为 null,创建 Optional 实例,否则创建空实例

isPresent() : 判断是否包含值

orElse(T t) : 如果调用对象包含值,返回该值,否则返回t

orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回 s 获取的值

map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回 Optional.empty()

flatMap(Function mapper):与 map 类似,要求返回值必须是Optional

上一篇下一篇

猜你喜欢

热点阅读