美文网首页
java8新特性

java8新特性

作者: 马晓钧 | 来源:发表于2018-12-23 15:48 被阅读0次

java8新特性

Lambda(核心)

用于快速的实现匿名内部类中的方法。

例子:
Runnable r = new Runnable() {
    @Override
    public void run() {
        System.out.println("do something.");      
    }
}

如果我们想要写一些线程,而每个线程中的实现很简单,就像例子中的只在控制台打印一句话,那么还需要多写4行代码,很麻烦,可读性也不高。下面,看下lambda的实现:

Runnable r = () -> System.out.println("do something.");
lambda的基础语法:
expression = (variable) -> action
  • variable:可以是一个变量,一个占位符,也可以是多个变量(x,y,z)。

  • action:实现的代码逻辑,如果一行处理不完,可以用“{}”将执行的代码包起来。

  • expression:返回的值。

使用姿势:
public class FunctionInterfaceDemo {
    @FunctionalInterface
    interface Predicate<T> {
        boolean test(T t);
    }
    /**
     * 执行Predicate判断
     *
     * @param age       年龄
     * @param predicate Predicate函数式接口
     * @return          返回布尔类型结果
     */
    public static boolean doPredicate(int age, Predicate<Integer> predicate) {
        return predicate.test(age);
    }
     
    public static void main(String[] args) {
        boolean isAdult = doPredicate(20, x -> x >= 18);
        System.out.println(isAdult);
    }
}

如上述代码所示,当一个接口类中只有一个方法,且接口类作为变量传入函数中的时候,就可以使用lambda函数。

四大内置接口

java8为lambda提供了4大内置接口,分别消费型接口、供给型接口、函数型接口、断言型接口。其它的很多接口都是这四种接口衍生出来的,我们可以根据入参和出参类型的不同灵活使用。

消费型接口示例(只有入参):

//消费money
public static void donation(Integer money, Consumer<Integer> consumer){
    consumer.accept(money);  
}
public static void main(String[] args) {
    donation(1000, money -> System.out.println("好心的麦乐迪为Blade捐赠了"+money+"元")) ;
}

供给型接口示例(只有出参):

//传入随机数,返回集合
public static List<Integer> supply(Integer num, Supplier<Integer> supplier){
       List<Integer> resultList = new ArrayList<Integer>()   ;
       for(int x=0;x<num;x++)  
           resultList.add(supplier.get());
       return resultList ;
}
public static void main(String[] args) {
    List<Integer> list = supply(10,() -> (int)(Math.random()*100));
    list.forEach(System.out::println);
}

函数型接口示例(入参出参都有):

//转换字符串为Integer
public static Integer convert(String str, Function<String, Integer> function) {
    return function.apply(str);
}
public static void main(String[] args) {
    Integer value = convert("28", x -> Integer.parseInt(x));
}    

断言型接口示例(有入参,出参为boolean类型):

//筛选出只有两个字的水果
public static List<String> filter(List<String> fruit, Predicate<String> predicate){
    List<String> f = new ArrayList<>();
    for (String s : fruit) {
        if(predicate.test(s)){
            f.add(s);
        }
    }
    return f;
}
public static void main(String[] args) {
    List<String> fruit = Arrays.asList("香蕉", "哈密瓜", "榴莲", "火龙果", "水蜜桃");
    List<String> newFruit = filter(fruit, (f) -> f.length() == 2);
    System.out.println(newFruit);
}

stream流

用于快速处理集合的数据(一般用于查找过滤)

创建流

我们常用的创建流的方式有两种,一是集合创建流(最常用),二是数组创建流,也有其它方式创建流,但是一般不用。

//1. 通过集合创建stream(推荐)
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();

//2. 通过Arrays中的静态方法
Integer[] intArray = new Integer[10];
Stream<Integer> stream2 = Arrays.stream(intArray);
处理过程
  1. 获取流。
  2. 中间操作。
  3. 终止操作。

常见的流处理函数

/**
 * Stream的中间操作:
     * filter:排除元素
     * distinct:去重
     * limit:给定数量
     * skip:跳过几个数量
     * map:实现函数
     * flatMap:扁平化
     * sorted:排序
 * Stream的终止操作:
     * allMatch,anyMatch,noneMatch:是否匹配元素
     * findFirst,findAny:返回元素
     * count,max,min:计数,最大,最小
     * forEach:迭代
     * reduce:归约
 */
并行流

java7中的Fork/Join框架,会将一个大任务拆分成多个小任务,并行的去执行,然后将各个小任务执行的结果进行合并,最终返回结果。缺点是代码太难写,每实现一次要写好多定制化的代码。

java8中提供了并行流的方式,底层用的就是Fork/Join框架,但只需要一句代码:

list.parallelStream()

与java7相比,人性化了很多。

总结
  1. stream流函数中需要传入的参数都是java8内置的lambda接口,因此,推荐在函数中直接写lambda。
  2. stream形式适用于集合数据快速的查找过滤等操作,当需要对集合中的数据进行很多的业务逻辑处理的时候,建议使用增强for循环。主要原因是lamdba写法不适合写的过长,处理过多业务逻辑,不利于后期维护。
练习
List<Transaction> transactions = null;

@Before
public void before(){
    //交易员
    Trader raoul = new Trader("Raoul", "Cambridge");
    Trader mario = new Trader("Mario", "Milan");
    Trader alan = new Trader("Alan", "Cambridge");
    Trader brian = new Trader("Brian", "Cambridge");

    //交易
    transactions = Arrays.asList(
            new Transaction(brian, 2011, 300),
            new Transaction(raoul, 2011, 1000),
            new Transaction(raoul, 2011, 400),
            new Transaction(mario, 2012, 710),
            new Transaction(mario, 2012, 700),
            new Transaction(alan, 2012, 950)
    );
}

/**
 * 1. 找出2011年发生的所有交易, 并按交易额排序(从低到高)
 */
@Test
public void test1() {
    transactions.stream()
            .filter((t) -> t.getYear() == 2011)
            .sorted(Comparator.comparingInt(Transaction::getValue))
            .forEach(System.out::println);
}

/**
 * 2. 交易员都在哪些不同的城市工作过?
 */
@Test
public void test2() {
    transactions.stream()
            .map((e) -> e.getTrader().getCity())
            .distinct()
            .forEach(System.out::println);
}

/**
 * 3. 查找所有来自剑桥的交易员,并按姓名排序
 */
@Test
public void test3() {
    transactions.stream()
            .filter((e) -> e.getTrader().getCity().equals("Cambridge"))
            .map((e) -> e.getTrader().getName())
            .sorted(Comparator.naturalOrder())
            .distinct()
            .forEach(System.out::println);
}

/**
 * 4. 返回所有交易员的姓名字符串,按字母顺序排序
 */
@Test
public void test4() {
    transactions.stream()
            .map((e) -> e.getTrader().getName())
            .sorted(Comparator.naturalOrder())
            .forEach(System.out::println);
}

/**
 * 5. 有没有交易员是在米兰工作的
 */
@Test
public void test5() {
    boolean b = transactions.stream()
            .anyMatch((e) -> e.getTrader().getCity().equals("Milan"));
    System.out.println(b);
}

/**
 * 6. 打印生活在剑桥的交易员的所有交易额之和
 */
@Test
public void test6() {
    Optional<Integer> optional = transactions.stream()
            .filter((e) -> e.getTrader().getCity().equals("Cambridge"))
            .map(Transaction::getValue)
            .reduce(Integer::sum);
    System.out.println(optional.get());
}

/**
 * 7. 所有交易中,最高的交易额是多少
 */
@Test
public void test7() {
    Optional<Integer> optional = transactions.stream()
            .map(Transaction::getValue)
            .max(Integer::compareTo);
    System.out.println(optional.get());
}

/**
 * 8. 找到交易额最小的交易
 */
@Test
public void test8() {
    Optional<Transaction> optional = transactions.stream()
            .min(Comparator.comparingInt(Transaction::getValue));
    System.out.println(optional.get());
}

时间API

简介
  1. java8对时间的api做了整理,主要为下面这三个类:LocalDate, LocalTime, LocalDateTime。从类名就可以看出,一个是日期,一个是时间,一个是全有。
  2. 我们平时使用的时候,尽量使用LocalDateTime。
  3. 在java8之前,我们使用的时间戳日期转换工具SimpleDateFormat是线程不安全的,在使用的时候没法抽成一个静态工具类,需要在每一个线程下重新new一个SimpleDateFormat。java8中提供的DateTimeFormatter则是线程安全的。
开发中常用例子

1--获取当前时间戳

@Test
public void test1() {
    //包含了日期和时间,可以转成秒,毫秒
    Instant timestamp = Instant.now();
    System.out.println(timestamp);
    //毫秒
    long milli = timestamp.toEpochMilli();
    System.out.println(milli);
    long second = timestamp.getEpochSecond();
    System.out.println(second);

}

2--时间戳与需要的日期格式相互转换

/**
 * 2.1 时间戳转成想要的日期格式
 */
@Test
public void test2() {
    String pattern = "yyyy-MM-dd HH:mm:ss";
    long time = Instant.now().toEpochMilli();
    //时间戳转成日期
    //1. 时间戳转成标准日期
    LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(time), ZoneId.systemDefault());
    System.out.println(localDateTime);
    //2. 标准日期转成我们需要的格式
    DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
    String format = df.format(localDateTime);
    System.out.println(format);
}

/**
 * 2.2 给定任意日期格式转成时间戳
 */
@Test
public void test3() {
    String pattern = "yyyy-MM-dd HH:mm:ss";
    //1. 将日期格式转成标准日期
    DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
    LocalDateTime localDateTime = LocalDateTime.parse("2018-12-17 10:00:00", df);
    System.out.println(localDateTime);
    //2. 转换成时间戳
    long milli = localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    System.out.println(milli);

}

3--时间日期差计算

/**
 * 3.1 计算时间差
 */
@Test
public void test4() throws InterruptedException {
    Instant ins1 = Instant.now();
    System.out.println(ins1.toEpochMilli());
    Thread.sleep(1000);
    Instant ins2 = Instant.now();
    System.out.println(ins2.toEpochMilli());
    long milli = Duration.between(ins1, ins2).toMillis();
    System.out.println(milli);
}


/**
 * 3.2 计算日期差
 */
@Test
public void test5() {
    LocalDate now = LocalDate.now();
    System.out.println(now);
    LocalDate birth = LocalDate.of(1994, 11,26);
    System.out.println(birth);
    //相隔日期
    Period period = Period.between(birth, now);
    System.out.println(period.getYears() + "-" + period.getMonths() + "-" + period.getDays());
    //相隔多少天
    long dayDiff = ChronoUnit.DAYS.between(birth, now);
    System.out.println(dayDiff);
}

4--日期加减

@Test
public void test6() {
    LocalDateTime today = LocalDateTime.now();
    LocalDateTime tor = today.plusDays(1);
    LocalDateTime yes = today.minusDays(1);
    System.out.println(yes);
    System.out.println(today);
    System.out.println(tor);
}

相关文章

网友评论

      本文标题:java8新特性

      本文链接:https://www.haomeiwen.com/subject/dksnkqtx.html