Java 8特性(一)

目录

 

一、Lambda表达式

1、语法格式:

(1)接口名 对象名=(参数类型1参数名1,....参数类型n 参数名n)->{方法体;}

(2)参数类型h 参数名n:接口中抽象方法的参数项

(3)->:表示连接操作

(4){}:存放重写的方法体内容。可以理解为对抽象方法的覆盖

2、简写格式:

(1)参数类型可以简写

(2)小括号,当参数只有1个时,可以省略  

(3){}、return、; 同时进行省略

二、函数式接口

(1)Supplier接口 --供给型接口:

(2)Consumer接口 --消费型接口:

(3)Function接口 --转换型接口:

(4)Predicate接口--断言型接口:

(5)Comparator接口--比较器接口:

三、Stream流:

1、使用Stream流处理集合数据:

2、获取Stream流的两种方式:

Collection集合提供了 default Stream stream()获取流;

Stream接口的静态方法 of 可以获取对应的流。

3、Stream 流的常用方法:

(1)forEach() :遍历流中的元素

(2)count():Stream 流提供的count方法,统计其中的元素个数

(3)filter(): 用于锅炉数据,返回符合条件的数据

(4)limit()方法: 可以对流的元素进行截取前几个

(5)skip()方法: 跳过前几个元素,可以使用skip方法获取一个截取之后的新的集合

(6)map() 可以将一种类型转换成另一种类型

(7)sorted()方法可以默认泛型排序,也可以自定义排序规则

(8)match()如果需要判断数据是否匹配指定的条件。可以使用match方法

(8.1)allMatch()判断所有元素是否满足条件

(8.2)anyMatch() 只要有一个满足条件就返回true

(8.3)noneMatch()所有的元素都不满足,返回true 

(9)collect() 方:法收集是一个 最终操作,返回Stream中元素集合,返回值类型是集合(List、Set、Map)或 字符串。

Collectors.toList():转成List集合

Collectors.toSet():转成Set集合

Collectors.toMap():转成map集合

Collectors.groupingBy() :可以按照指定内容进行统计

Collectors.mapping():将一种数据类型的集合映射成另一种数据类型

4、Parallel Stream 并行流:


 

一、Lambda表达式

  • Lambda 表达式本质是一个匿名函数,用于把函数作为参数,传入方法中,实现函数式编程风格。
  • 使用Lambda 表达式可以使代码变的更加简洁紧凑。

1、语法格式:

(1)接口名 对象名=(参数类型1参数名1,....参数类型n 参数名n)->{方法体;}

(2)参数类型h 参数名n:接口中抽象方法的参数项

(3)->:表示连接操作

(4){}:存放重写的方法体内容。可以理解为对抽象方法的覆盖

2、简写格式:

(1)参数类型可以简写

(2)小括号,当参数只有1个时,可以省略  

(3){}、return、; 同时进行省略

package com.yuan.lambda;

public class Demo02 {
    public static void main(String[] args) {
        swim(new ISwim() {
            @Override
            public void swimming() {
                System.out.println("Frog蛙泳");
            }
        });
        swim(()-> System.out.println("Duck蛙泳"));
    }
    public static void swim(ISwim s1){
        System.out.println("进入swim方法");
        s1.swimming();
        System.out.println("结束swim方法");
    }
}
interface ISwim{
    void swimming();
}

    二、函数式接口

               在 Java 8 中专门有一个包放函数式接口java.util.function,该包下的所有接口都有 @FunctionalInterface 注解,提供函数式编程方式。下面是最常用的几个接口。

    (1)Supplier接口 --供给型接口:

    @FunctionalInterface
    public interface Supplier<T> {
        public abstract T get();
    }

    java.util.function.Supplier<T> 接口 - 方法没有参数,有返回值--供给型接口。

    它意味着"供给" , 对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据。
    供给型接口,通过Supplier接口中的get方法可以得到一个值,无参有返回的接口。

    //案例
    public class Demo01 {
        public static void main(String[] args) {
            System.out.println("进入到main方法中");
            printMax(()->{
                System.out.println("进入到get方法中");
                Integer[] array={1,2,3,4,5};
                Integer number= Collections.max(Arrays.asList(array));
                System.out.println("在get中找到最大值了"+number);
                return number;
            });
            Integer number = number(() -> {
                while(true) {
                    int number1 = (int) (Math.random() * 11 + 10);
                    if((number1&1)==0){
                        return number1;
                    }
                }
            });
    
            System.out.println("随机数为:"+number);
    
        }
    
       public static Integer number(Supplier<Integer> sup){
            Integer ranNum=sup.get();
            return ranNum;
       }
       public static void printMax(Supplier<Integer> sup){
           System.out.println("机内到printMax方法中");
           Integer number=sup.get();
           System.out.println("printMax要打印的sup获取的最大值"+number);
       }
    }
    

    (2)Consumer接口 --消费型接口:

    @FunctionalInterface 
    public interface Consumer<T> { 
        public abstract void accept(T t); 

    java.util.function.Consumer<T> 接口则正好相反 --方法有参数,没有返回值,它不是生产一个数据,而是消费一个数据,其数据类型由泛型参数决定。 --消费型接口

    Consumer消费型接口,可以拿到accept方法参数传递过来的数据进行处理, 有参无返回的接口。

    //案例
    public class Demo02 {
        public static void main(String[] args) {
            //转大写
            caseLetter(t->System.out.println(t.toUpperCase()),"HelloWorld");
            //转小写
            caseLetter(t->System.out.println(t.toLowerCase()),"HelloWorld");
            //先转大写,再转小写
            caseLetters(t->System.out.println(t.toUpperCase()),
                    t->System.out.println(t.toLowerCase()),"HelloWorld");
    
        }
        public static void caseLetter(Consumer<String> consumer,String str){
            consumer.accept(str);
        }
        public static void caseLetters(Consumer<String> consumer1,Consumer<String> consumer2,String str){
            consumer1.andThen(consumer2).accept(str);
        }
    }
    

    (3)Function接口 --转换型接口:

    @FunctionalInterface 
    public interface Function<T, R> { 
        public abstract R apply(T t); 

    java.util.function.Function<T,R>接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件, 后者称为后置条件。有参数有返回值。----- 此方法接收一个参数,加工处理成另一种,称为转换型接口
    Function转换型接口,对apply方法传入的T类型数据进行处理,返回R类型的结果,有参有返回的接口。使用的场景 例如:将 String类型转换为 Integer类型。

    //案例
    public class Demo03 {
        public static void main(String[] args) {
            // 1.获取字符串的长度
            Function<String, Integer> f1 = s1 -> s1.length();
            test(f1, "1234abc");
    
            // 2.截取字符串的前3位,将其转换成数字
            test(s1 -> Integer.parseInt(s1.substring(0, 3)), "123aneii");
    
            test(s1 -> s1.length(), len -> new int[len], "abc");
        }
    
        public static void test(Function<String, Integer> function, String str) {
            Integer number = function.apply(str);
            System.out.println(number);
        }
    
        public static void test(Function<String, Integer> f1,
                                Function<Integer, int[]> f2,
                                String str) {
            int[] arr = f1.andThen(f2).apply(str);
            System.out.println(Arrays.toString(arr));
        }
    }

    (4)Predicate接口--断言型接口:

    @FunctionalInterface 
    public interface Predicate<T> { 
        public abstract boolean test(T t); 

    Predicate接口用于做判断,返回boolean类型的值

    有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。这时可以使用

    java.util.function.Predicate<T> 接口。------接收一个参数,返回一个boolean类型的值,称为判断型接口

    //案例
    public class Demo04 {
        public static void main(String[] args) {
            int number = new Random().nextInt(200);
    
            // 1.判断此数字是否大于等于100
            method(num -> num >= 100, number);
    
            // 2.判断此数字是否是偶数
            method(num -> (num & 1) == 0, number);
    
            methods(num -> num >= 100, num -> (num & 1) == 0, number);
        }
    
        public static void method(Predicate<Integer> p, Integer num) {
            boolean b = p.test(num);
            System.out.println("数字num:" + num + "判断后的结果为:" + b);
        }
    
        public static void methods(Predicate<Integer> p1, Predicate<Integer> p2, Integer num) {
            boolean b = p1.and(p2).test(num);
            System.out.println("数字num:" + num + "是否大于100并且为偶数:" + b);
    
            boolean b1 = p1.or(p2).test(num);
            System.out.println("数字num:" + num + "是否大于100或者为偶数:" + b1);
    
            boolean b2 = p1.negate().test(num);
            System.out.println("数字num:" + num + "是否不大于100:" + b2);
    
            boolean b3 = p2.negate().test(num);
            System.out.println("数字num:" + num + "是否不为偶数:" + b3);
        }
    }

    (5)Comparator接口--比较器接口:

    比较器接口,用于比较指定元素值的大小。Java8版本中,添加了多个新的default方法,用于比较器合并、反转等操作。

    
    List<String> langList = Arrays.asList("Basic", "QBasic","HTML", "c", "c++", "PowerBuilder", "go", "Visual Basic", "c#","java");
    
    // 按照ASCII码比较
    Comparator<String> comparator1 = (s1, s2) -> {
        return s1.compareTo(s2);
    };
    
    // 按照长度比较
    Comparator<String> comparator2 = (s1, s2) -> {
        return s1.length() - s2.length();
    };
    
    // 先比较长度,再比较ASCII码
    Comparator<String> comparator3 = comparator2.thenComparing(comparator1);
    
    // 在comparator3的基础上,反转条件
    Comparator<String> comparator4 = comparator2.reversed();
    
    // 按照指定Comparator,进行排序
    langList.sort(comparator2);

    三、Stream流:

    • java.util.Stream 表示能应用在一组元素上一次执行的操作序列。
    • Stream操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,可以连续完成多个操作。

    1、使用Stream流处理集合数据:

    当我们需要对集合中的元素进行操作的时候,除了必需的添加、删除、获取外,最典型的就是集合遍历。我们来体验 集合操作数据的弊端,需求如下:

    package com.yuan.stream;
    
    import java.util.ArrayList;
    import java.util.Collections;
    
    public class Demo01 {
        public static void main(String[] args) {
            ArrayList<String> list = new ArrayList<>();
            Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
    
            // 1.拿到所有姓张的
            ArrayList<String> zhanglist = new ArrayList<String>();
            for (String string : list) {
                if (string.startsWith("张")) {
                    zhanglist.add(string);
                }
            }
    
            ArrayList<String> threeList = new ArrayList<String>();
            // 2.拿到名字长度为3的字
            for (String string : zhanglist) {
                if (string.length() == 3) {
                    threeList.add(string);
                }
            }
            System.out.println(threeList);
    
            //使用stream 流
            list.stream().filter(s1->s1.charAt(0)=='张').filter(s1->s1.length()==3).forEach(s1-> System.out.println(s1));
    
        }
    }
    

    2、获取Stream流的两种方式:

    java.util.stream.Stream<T>是JDK 8新加入的流接口。 获取一个流非常简单,有以下几种常用的方式:

    1. Collection集合提供了 default Stream<E> stream()获取流;

    2. Stream接口的静态方法 of 可以获取对应的流。

    package com.yuan.stream;
    
    import java.sql.Array;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.List;
    import java.util.stream.Stream;
    
    //Stream 流的获取方式
    //1、Collection 集合提供了default Stream<E>  stream()获取流
    //2、Stream 接口的静态方法of可以获取对应的流
    public class Demo02 {
        public static void main(String[] args) {
    
            //方式一: Stream 的静态方法of
            Stream<String> s1 = Stream.of("aa", "bb", "cc");
            System.out.println(s1);
    
            String[] arr={"aa", "bb", "cc"};
            Stream<String> s2 = (Stream<String>) Stream.of(arr);
            System.out.println(s2);
    
            int[] numbers={1,2,3,4};
            Stream<int[]> s3 = Stream.of(numbers);
            System.out.println(s3);
    
            //方式二:  Collection 接口中Stream方法
            List<String> list = Arrays.asList("aa", "bb", "cc");
            Stream<String> s4 = list.stream();
            System.out.println(s4);
    
            HashSet<String> set = new HashSet<>(list);
            Stream<String> s5 = set.stream();
            System.out.println(s5);
    
            HashMap<String, Integer> map = new HashMap<>();
            System.out.println(map.entrySet().stream());
        }
    }
    

    3、Stream 流的常用方法:

    Stream流模型的操作很丰富,这里介绍一些常用的API。

    这些方法可以被分成两种:

    终结方法:返回值类型不再是 Stream类型的方法,不再支持链式调用。本小节中,终结方法包括 count和 forEach 方法。

    非终结方法:返回值类型仍然是 Stream类型的方法,支持链式调用。(除了终结方法外,其余方法均为非终结 方法。)

    (1)forEach() :遍历流中的元素

    (2)count():Stream 流提供的count方法,统计其中的元素个数

    (3)filter(): 用于锅炉数据,返回符合条件的数据

    (4)limit()方法: 可以对流的元素进行截取前几个

    (5)skip()方法: 跳过前几个元素,可以使用skip方法获取一个截取之后的新的集合

    package com.yuan.method;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.Collections;
    import java.util.List;
    import java.util.stream.Stream;
    
    public class Demo01 {
        public static void main(String[] args) {
            List<String> list=new ArrayList<>();
            Collections.addAll(list,"迪丽热巴","陶白白","吴磊","易烊千玺","刘亦菲");
    
            //1、forEach() 获取流,遍历集合中的元素
            Stream<String> s1 = list.stream();
            s1.forEach(System.out::println);
            //2、count():Stream 流提供的count方法,统计其中的元素个数
            Stream<String> s2 = list.stream();
            long count = s2.count();
            System.out.println(count);
            //3、filter(): 用于锅炉数据,返回符合条件的数据
            list.stream().filter(str->str.length()==3).forEach(System.out::println);
            System.out.println("=========================");
            //4、limit()方法: 可以对流的元素进行截取前几个
            list.stream().limit(2).forEach(str-> System.out.print(str+" "));
    
            System.out.println();
            System.out.println("===============");
            //5、skip()方法: 跳过前几个元素,可以使用skip方法获取一个截取之后的新的集合
            list.stream().skip(0).forEach(str-> System.out.print(str+" "));
        }
    }
    

    (6)map() 可以将一种类型转换成另一种类型

    (7)sorted()方法可以默认泛型排序,也可以自定义排序规则

    (8)match()如果需要判断数据是否匹配指定的条件。可以使用match方法

    (8.1)allMatch()判断所有元素是否满足条件

    (8.2)anyMatch() 只要有一个满足条件就返回true

    (8.3)noneMatch()所有的元素都不满足,返回true 

    package com.yuan.method;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.stream.Stream;
    
    public class Demo02 {
        public static void main(String[] args) {
            ArrayList<String> list=new ArrayList<>(Arrays.asList("32","22","45","11","33"));
            Stream<String> s1 = list.stream();
            //6、map() 可以将一种类型转换成另一种类型
            Stream<Integer> s2 = s1.map(str -> Integer.parseInt(str));
    //        s2.forEach(number-> System.out.println(number));
            System.out.println("==========sorted=========");
            //如果满要将数据排序、可以使用 sorted方法
            //使用泛型类型的默认排序规则排序
            // s2.sorted().forEach(number-> System.out.println(number))
            //使用自定义的Comparator比较规则排序
    
            s2.sorted((a,b)->b-a).forEach(number-> System.out.println(number));
    
            System.out.println("==========distinct=========");
            Stream.of(1,3,2,1,3,4,5,6).distinct().forEach(System.out::println);
    
            System.out.println("==========match=========");
            //如果需要哦按段数据是否匹配指定的条件。可以使用match方法
            //判断所有的元素是否满足条件
            boolean b1 = Stream.of(1, 3, 2, 1, 3, 4, 5, 6).allMatch(number -> number > 0);
            System.out.println("allmatch: "+b1);
    
            //只要有一个满足条件就返回true   ||  or
            boolean b2 = Stream.of(1, 3, 2, 1, 3, 4, 5, 6).anyMatch(number -> number > 5);
            System.out.println("anymatch: "+b2);
    
            //所有的元素都不匹配,返回true
            boolean b3 = Stream.of(1, 3, 2, 1, 3, 4, 5, 6).noneMatch(number -> number > 100);
            System.out.println("nonematch: "+b3);
    
    
        }
    }
    

    (9)collect() 方:法收集是一个 最终操作,返回Stream中元素集合,返回值类型是集合(List、Set、Map字符串

    Collectors.toList():转成List集合

    Collectors.toSet():转成Set集合

    Collectors.toMap():转成map集合

    Collectors.groupingBy() :可以按照指定内容进行统计

    Collectors.mapping():将一种数据类型的集合映射成另一种数据类型

    package com.yuan.method;
    
    import java.util.*;
    import java.util.stream.Collectors;
    
    public class Demo03 {
        public static void main(String[] args) {
            List<String> langList = Arrays.asList("abc", "deft", "gbhk", "bac", "fgh");
            //将结果过滤,收集至List集合
            List<String> list = langList.stream().filter(str -> str.toUpperCase().contains("B")).collect(
                    Collectors.toList()
            );
            System.out.println(list);
            //将过滤结果收集到Set集合
            Set<String> set = langList.stream().filter(str -> str.toUpperCase().contains("B")).collect(
                    Collectors.toSet()
            );
            System.out.println(set);
    
            //将过滤结果收集到map集合
            Map<String, Integer> map = langList.stream().distinct().filter(s -> s.toUpperCase().contains("B")).collect(
                    Collectors.toMap(s -> s, s -> s.length())
            );
            System.out.println(map);
            //按照字符串的长度统计
            Map<Integer, List<String>> groupMap = langList.stream().collect(
                    Collectors.groupingBy(str -> str.length())
            );
            System.out.println(groupMap);
    
            //按照字符串长度转成集合
            List<Integer> mappingList = langList.stream().collect(
                    Collectors.mapping(str -> str.length(), Collectors.toList())
            );
            System.out.println(mappingList);
        }
    }
    

    4、Parallel Stream 并行流:

    Stream有串行和并行两种,串行Stream上的操作是在一个线程中依次完成,而并行Stream则是在多个线程上同时执行。

    int max = 1000000;
    List<String> values = new ArrayList<>(max);
    for (int i = 0; i < max; i++) {
        UUID uuid = UUID.randomUUID();
        values.add(uuid.toString());
    }

    //串行排序

    long t0 = System.nanoTime();//返回豪微秒
    long count = values.stream().sorted().count();
    System.out.println(count);

    long t1 = System.nanoTime();

    long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
    System.out.println(String.format("串行排序,耗时共计: %d 毫秒", millis));

    //并行排序

    long t0 = System.nanoTime();

    long count = values.parallelStream().sorted().count();
    System.out.println(count);

    long t1 = System.nanoTime();

    long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
    System.out.println(String.format("并行排序,耗时共计: %d 毫秒", millis));

    并行的执行效率高,但是不安全,在使用时要注意线程安全,

     

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包

    打赏作者

    呼哧呼哧.

    栓Q!!!

    ¥1 ¥2 ¥4 ¥6 ¥10 ¥20
    扫码支付:¥1
    获取中
    扫码支付

    您的余额不足,请更换扫码支付或充值

    打赏作者

    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

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

    余额充值