Java8新特性

Lambda表达式

示例

static List<Employee> employees = Arrays.asList(
            new Employee("张三", 12, 5000),
            new Employee("李四", 20, 6000),
            new Employee("王二", 37, 4000),
            new Employee("周五", 19, 3000),
            new Employee("今天", 80, 9000)
    );

public interface Mypredict<T> {
    boolean test(T t);
}
@Test
public void test(){
     List<Employee> eps = dodo(employees, (e) -> e.getWage() > 500);
     eps.forEach(System.out::println);
}
public static List<Employee> dodo(List<Employee> list, Mypredict<Employee> me) {
        List<Employee> employees = new ArrayList<>();
        for (Employee employee : list) {
            if (me.test(employee)) {
                employees.add(employee);
            }
        }
        return employees;
 }
  • 语法格式

    • 1.无参数无返回值,Lambda箭头操作符' -> ',左边表示参数列表,右边为函数式结构的实现@FunctionalInterface的实现,类比匿名内部类
    @FunctionalInterface
    public interface LamTest {
        public void T();
    }
    
    @Test
    public void test(){
    LamTest lamTest=()->System.out.println("lambda的无参数无返回格式");
            lamTest.T();
    }
    
    • 2.一个参数,无返回值
    @FunctionalInterface
    public interface LamTest {
        public void T(String str);
    }
    
    @Test
    public void test(){
     LamTest lamTest=(x)->System.out.println(x);
            lamTest.T("hello");
    }
    
    • 3.多个参数,带有返回值
    @FunctionalInterface
    public interface LamTest {
        public StringBuilder T(String str,String str2);
    }
    @Test
    public void test(){
    LamTest lamTest=(x,y)->{
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append(x).append(y);
                return stringBuilder;
            };//有多条语句是使用大括号括起来,使用return返回目标值
    LamTest lamTest1 = (x, y) -> new StringBuilder().append(x).append(y);//单条语句时,可以省略return
            System.out.println(lamTest.T("zhou","真"));
            System.out.println(lamTest1.T("zhou","假"));
    }
    
    • 注意事项:
      • lambda表达式与匿名内部类一样,可以调用,但是不可以对局部变量进行改变,虽没有显式声明,但是java8中默认将表达式中使用的局部变量设置为了final。
      • @FunctionalInterface是用来检验是否为函数式接口(只存在一个抽象方法的接口)
      • lambda表达式不需要声明参数类型,jvm使用"类型推断"可自动判断参数类型,如果声明,则所有参数需要声明类型
      • 当参数列表只有一个参数传入时候,可以省略括号,但不建议这样做

    lambda表达式与匿名内部类示例

    ​ 函数式接口

    @FunctionalInterface
    public interface Mypredict<T> {
        boolean test(T t);
    }
    
public void test() {
        //单条语句带返回值
        dodo(employees, (e) -> e.getWage() > 5000).stream().forEach(System.out::println);
        //多条语句带返回值
        dodo(employees, (e) -> {
            boolean b = e.getWage() > 5000;
            return b;
        }).stream().forEach(System.out::println);
        //匿名内部类
        dodo(employees, new Mypredict<Employee>() {
            @Override
            public boolean test(Employee employee) {
                return employee.getWage()>5000;
            }
        }).stream().forEach(System.out::println);
    }
  //具体方法
    public static List<Employee> dodo(List<Employee> list, Mypredict<Employee> me) {
        List<Employee> employees = new ArrayList<>();
        for (Employee employee : list) {
            if (me.test(employee)) {
                employees.add(employee);
            }
        }
        return employees;
    }

Java8提供的四个核心函数式接口:

  1. Comsumer<T> : 消费型接口

    ​ void accept(T t);

  2. Supplier<T>: 供给型接口

    ​ T get();

  3. Functional<T,R> : 函数型接口

    ​ R apply(T t);

  4. Predicate<T>: 断言型接口

    ​ boolean test(T t);

lambda表达式方法引用

如果lambda表达式的内容已经有现有方法实现,可以使用"方法引用",调用现有的方法

语法格式:

  1. 对象::实例方法名

            //before
            Consumer com=x->System.out.println(x);
            com.accept("hello");
            //对象::实例方法名
            PrintStream ps = System.out;
            Consumer con = ps::println;//System.out::println
            con.accept("hello");
    
  1. 类::静态方法名

          //before
            Comparator<Integer> comparator = (x, y) -> Integer.compare(x,y);
            System.out.println(comparator.compare(1, 3));
            //类::静态方法名
            Comparator<Integer> comparator1 = Integer::compareTo;
            comparator1.compare(1, 3);
    
  2. 类::实例方法名(要求参数列表中的第一个参数需要是方法的调用者,另一个参数为被调用的方法所需的参数传入)

         //before
            BiPredicate<String, String> biPredicate = (x, y) -> x.equals(y);
            System.out.println(biPredicate.test("heel", "sdad"));
            //after
            BiPredicate<String, String> biPredicate1 = String::equals;
            System.out.println(biPredicate.test("heel", "sdad"));
    
  3. 构造器引用(构造器的参数列表需要与函数式接口中的抽象方法列表一致)

    无参时:

     Supplier<Employee> supplier = Employee::new;
      System.out.println(supplier.get().getClass().getName());
    

    有参时(需要目标类提供带参构造器):

         //before
            Function<String,Employee> employeeFunction=(x)->new Employee(x);
            System.out.println(employeeFunction.apply("name"));
            //构造引用
            Function<String, Employee> employeeFunction1 = Employee::new;
            System.out.println(employeeFunction1.apply("TTTT"));
    
  1. 数组引用:

      //before
            Function<Integer, String[]> function = (x) -> new String[x];
            System.out.println(function.apply(6).length);
            //数组引用
            Function<Integer, String[]> function1 = String[]::new;
            ps.println(function1.apply(10).length);
    

Stream()API

示例

static List<Employee> employees = Arrays.asList(
            new Employee("张三", 12, 5000),
            new Employee("李四", 20, 6000),
            new Employee("王二", 37, 4000),
            new Employee("周五", 19, 3000),
            new Employee("今天", 80, 9000)
    );
@Test
public void test(){
    employees.stream().filter((e) -> e.getWage() > 7000).forEach(System.out::println);
}
  • Stream流的创建:
  1. 通过Collection系列的集合创建:

     List<String> a = new ArrayList<String>();
            a.add("aa");
            a.add("bb");
            a.add("cc");
            Stream stream =a.stream();
    
  1. 通过Arrays中的静态方法stream()获取数组流

    Stream<String> stream1 = Arrays.stream(new String[10]);
    
  2. 通过Stream中的静态方法of:

    Stream<String> stream1 = Arrays.stream(new String[10]);
    
  3. 创建无限流

    1. 迭代
    Stream<Integer> stream3 = Stream.iterate(0, x -> x + 2);
    
    1. 生成
     Stream<Double> stream4 = Stream.generate(Math::random);//方法引用
     Stream<Double> stream5 = Stream.generate(() -> Math.random());//方法调用
    
  • Stream流的中间操作(多个中间操作可称为流水线操作,只有当终止操作存在时才会触发中间操作,“惰性求值

    ”),生成新的流

    • filter(Predicate p)
    • distinct()筛选,去除掉重复元素(需要在源元素中重写hashcode()和equals()操作)
    • limit(n)取流的前n个元素
    • skip(n)与limit()互补,丢弃流的前n个元素,当流中元素不足n时,返回空流。
  • Stream流中的map映射(将流中的每一个元素变成一个新的流,再将这些流放入一个流Stream<Stream<T>>):

    @Test
    public void T{
    List<String> a = new ArrayList<String>();
            a.add("aaa");
            a.add("bbb");
            a.add("ccc");
          Stream<Stream<Character>> streamStream= a.stream().map(Test::d);
            streamStream.forEach(e -> {
                e.forEach(System.out::println);
            });
    }
    public static Stream<Character> d(String string) {
            List<Character> characters = new ArrayList<>();
            for (Character c : string.toCharArray()) {
                characters.add(c);
            }
            return characters.stream();
        }
    
  • Stream流中的flatmap映射(将所有的元素按照需求变更后重新放置再一个流中Stream<T>):

    
    @Test
    public void T{
    List<String> a = new ArrayList<String>();
            a.add("aaa");
            a.add("bbb");
            a.add("ccc");
        
    Stream<Character> characterStream=a.stream().flatMap(e->{
               List<Character> characters = new ArrayList<>();
               for (Character character : e.toCharArray()) {
                   characters.add(character);
               }
               return characters.stream();
           });
           characterStream.forEach(x->System.out.println(x));
    }
    
  • Stream的查找与匹配

    1. allMatch--检查是否匹配所有元素
    2. anyMatch--检查是否至少匹配一个元素
    3. noneMatch--检查是否没有匹配所有元素
    4. findFirst--返回第一个元素
    5. count--返回流中的元素的总个数
    6. max--返回流中的最大值
    7. min--返回流中最小值
  • Strem规约(通过将流中的元素反复结合返回一个T/Optional<T>)

    • reduce(T iden,BinaryOperator b)
    //计算平方和
    List<Integer> nums = new ArrayList<>();
            nums.add(2);
            nums.add(4);
            nums.add(3);
            nums.add(7);
            Integer reduce = nums.stream().reduce(0, (x, y) -> x + y*y);//0相当于初始值x
            System.out.println(reduce);
    
    • reduce(BinaryOperator b)
    //计算总和 
    Optional<Integer> reduce1 = nums.stream().reduce(Integer::sum);
            System.out.println(reduce1);
    
  • Stream的收集collect(将流转换成其他形式,接受一个Collector接口的实现(一般使用Collectors工具类及其静态方法)用于给Stream中元素做汇总)

  • Stream的分组,通过collect(Collectors.groupingBy())来进行分组,返回一个Map类型

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,117评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,963评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,897评论 0 240
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,805评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,208评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,535评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,797评论 2 311
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,493评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,215评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,477评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,988评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,325评论 2 252
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,971评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,807评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,544评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,455评论 2 266

推荐阅读更多精彩内容