Lambda表达式&接口更新&方法引用&函数式接口&Stream流

Lambda表达式&接口更新&方法引用&函数式接口&Stream流

    • Lambda
      • 1.程序启动三种不同的表现形式
      • 2.Lambda表达式的标准格式
      • 3.练习 Lambda 无参无返回值
      • 4.练习 Lambda 有参无返回值
      • 5.练习 Lambda 有参有返回值
          • 方式1
          • 方式2
      • 6.Lambda 表达式的省略
      • 7.Lambda表达式的注意事项
      • 8.Lambda表达式和匿名内部类的区别
          • 所需类型不同
          • 使用限制不同
          • 实现原理不同
    • 接口更新
        • 接口中的默认方法
        • 接口中的静态方法
        • 接口中的私有方法
        • 具体实现
    • 方法引用
        • 方法引用符
        • 引用类方法
        • 引用对象的实例方法
        • 引用类的实例方法
        • 引用构造器
    • 函数式接口
        • 概述
        • 函数式接口用作方法的参数
        • 函数式接口作为方法的返回值
      • 常用接口
          • 1.Supplier接口
            • test得到数组最大值
          • 2.consumer接口
            • test按要求打印信息
          • 3.Predicate接口
            • test筛选条件
          • 4.Function接口
            • 计算肖猛真实年龄
    • Stream流
        • 体验Stream流
        • Stream流的生成方式
        • 1.Stream流中间操作filter,limit,skip concate,distinct
        • 2.Stream流中间操作sorted()
        • 3.Stream流中间操作map,mapToInt
        • 4.Stream流终结操作forEach,count
        • 6.Stream流的收集操作
        • Stream流综合练习

Lambda

1.程序启动三种不同的表现形式

1.正常静态代理启动

2.匿名内部类启动

3.Lambda表达式启动

package com.xm.lambda;

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("程序启动---正常静态代理启动");
    }
}
public class Demo1 {
    public static void main(String[] args) {
        //正常启动
        new Thread(new MyRunnable()).start();
        //匿名内部类
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("程序启动---匿名内部类");
            }
        }).start();
        //无参 lambda
        new Thread(()-> System.out.println("程序启动---Lambda")).start();
    }
}

2.Lambda表达式的标准格式

  • 格式:(形式参数)->{代码块}

  • 形式参数:如果由多个参数,参数之间用逗号隔开,没有参数留空即可

  • ->:固定写法,代表指向动作

  • 代码块:是我们具体要做的事情,也就是以前我们写方法题内容


3.练习 Lambda 无参无返回值

package com.xm.lambda;

interface Eat {
    void eat();
}

class EatImpl implements Eat {
    @Override
    public void eat() {
        System.out.println("多吃蔬菜,身体健康----正常代理");
    }
}

public class Demo2 {
    public static void main(String[] args) {
        //正常代理
        Eat e = new EatImpl();
        e.eat();
        //匿名内部类
        new Eat() {
            @Override
            public void eat() {
                System.out.println("多吃蔬菜,身体健康----匿名内部类");
            }
        }.eat();
        //Lambda
        e = () -> System.out.println("多吃蔬菜,身体健康----匿名内部类");
        e.eat();
    }
}

4.练习 Lambda 有参无返回值

package com.xm.lambda;
interface Flyable {
    void fiy(String s);
}
class FlyableImpl implements Flyable{
    @Override
    public void fiy(String s) {
        System.out.println(s);
        System.out.println("正常代理");
    }
}
public class Demo3 {
    public static void main(String[] args) {
        //正常代理
        useFlyable(new FlyableImpl());
        //匿名内部类
        useFlyable(new Flyable() {
            @Override
            public void fiy(String s) {
                System.out.println(s);
                System.out.println("匿名内部类");
            }
        });
        //Lambda
        useFlyable((String s)->{
            System.out.println(s);
            System.out.println("Lambda");
        });

    }
    public static void useFlyable(Flyable f)
    {
        f.fiy("多吃蔬菜,身体健康!!!!");
    }
}

5.练习 Lambda 有参有返回值

方式1

与方式2相同

package com.xm.lambda;

interface Addable {
    int add(int x, int y);
}

class AddableImpl implements Addable {
    @Override
    public int add(int x, int y) {
        System.out.println("正常代理");
        return x + y;
    }
}

public class Demo4 {
    public static void main(String[] args) {
        //正常代理
        useAffable(new AddableImpl());
        //匿名内部类
        useAffable(new Addable() {
            @Override
            public int add(int x, int y) {
                System.out.println("匿名内部类");
                return x + y;
            }
        });
        //Lambda
        useAffable((x, y) -> {
            System.out.println("Lambda");
            return x + y;
        });

    }

    public static void useAffable(Addable a) {
        System.out.println(a.add(20, 30));
    }
}

方式2

与方式1相同

package com.xm.lambda;

interface Addable {
    int add(int x, int y);
}

class AddableImpl implements Addable {
    @Override
    public int add(int x, int y) {
        System.out.println("正常代理");
        return x + y;
    }
}

public class Demo4 {
    public static void main(String[] args) {
        //正常代理
        System.out.println(new AddableImpl().add(20, 30));
        //匿名内部类
        System.out.println(new Addable() {
            @Override
            public int add(int x, int y) {
                System.out.println("匿名内部类");
                return x + y;
            }
        }.add(30, 40));
        //Lambda 1
        Addable e = (x, y) -> {
            System.out.println("Lambda1");
            return x + y;
        };
        System.out.println(e.add(40, 50));
        //Lambda 2
        System.out.println(((Addable) (x, y) -> {
            System.out.println("Lambda2");
            return x + y;
        }).add(40, 50));

    }

}

6.Lambda 表达式的省略

  • 参数类型可以省略,在多参的情况下,不能只省略一个
  • 只有一个参数的时候,可以省略小括号
  • 如果代码块的语句只有一条,可以省略大括号和分号,return 语句可以省略

7.Lambda表达式的注意事项

  • 使用Lambda必须有接口,接口中仅有一个抽象方法
  • 必须要有上下文环境,才能推导出Lambda对应的接口
    • 根据局部变量的赋值得知Lambda对应的接口:Runnable r=()->System.out.print(“你好”);
    • 根据调用的方法的参数得知Lambda对应的接口: new Thread()->System.out.println(“你好”).start();
    • 作为返回值为接口类型的返回值

8.Lambda表达式和匿名内部类的区别

所需类型不同
  • 匿名内部类:可以是接口,抽象类,具体类
  • Lambda:只能是接口
使用限制不同
  • 如果接口中有且仅有一个抽象方法,可以用Lambda,或匿名内部类
  • 如果接口中有多于一个抽象方法,只能用匿名内部类
实现原理不同
  • 匿名内部类:编译之后,产生一个单独的.class 字节码文件
  • Lambda:编译之后,没有一个单独的.class字节码文件。对应的字节码会在运行的时候动态生成

接口更新

正常 属性 public static final

正常方法 public abstract

  • 默认方法 Java8
  • 静态方法 Java8
  • 私有方法 Java9
接口中的默认方法

不强制重写,可以重写(去掉default); 接口中可以省略public

接口中的静态方法

不能重写,静态方法只能通过接口名调用,不能通过实现类名或者对象名调用

public可以省略,static不能省略

接口中的私有方法

private void show()

private static void show()

默认方法可以调用私有的静态方法和非静态方法

静态方法只能调用私有的静态方法

具体实现
package com.xm.接口;

interface MyInterface {

    void show1();

    void show2();

    default void show3() {
        System.out.println("show3---接口");
    }
    static void show4()
    {
        System.out.println("show4---接口中的静态方法只能被接口调用");
    }
    default void method1()
    {
        System.out.println("method1");
        show();
    }
    default void method2()
    {
        System.out.println("method2");
        show();
    }
    private void show(){
        System.out.println("你好!");
        System.out.println("你也好!");
    }
    static void method3(){
        System.out.println("method3");
        showStatic();
    }
    private static void showStatic()
    {
        System.out.println("你好!");
        System.out.println("你也好!");
    }

}

class MyInterfaceImpl implements MyInterface {
    @Override
    public void show1() {
        System.out.println("show1");
    }

    @Override
    public void show2() {
        System.out.println("show2");
    }

    @Override
    public void show3() {
        System.out.println("show3---实现类");
    }
}

public class Demo1 {
    public static void main(String... args)//可变参数
    {
       MyInterface mi= new MyInterfaceImpl();
       mi.show1();
       mi.show2();
       mi.show3();
       MyInterface.show4();
       mi.method1();
       mi.method2();
       MyInterface.method3();

    }
}

方法引用

方法引用符

::该符号为引用运算符,它所在的表达式被称为方法引用

  • Lambda 表达式中的参数s 传递给System.out 这个对象调用的println方法去处理
  • 方法引用 直接使用System.out 中的println方法来取代Lambda ,代码更加整洁
package com.xm.方法引用;
interface Printable {
    void printInt(int x);
}
public class Demo1 {
    public static void main(String[] args) {
        usePrintable(i->System.out.println(i));
        usePrintable(System.out::println);
        System.out.println(666);
        ((Printable) i->System.out.println(i)).printInt(8888);
        ((Printable)System.out::println).printInt(8888);
        System.out.println(8888);

    }
    public static void usePrintable(Printable p)
    {
        p.printInt(6666);
    }
}

引用类方法

实际上是引用类的静态方法

package com.xm.方法引用;

interface Converter {
    int convert(String s);
}

public class Demo2 {
    public static void main(String[] args) {
        //第一种写法
        useConverter(s -> Integer.parseInt(s));//省略return
        useConverter(Integer::parseInt);
        //Lambda表达式被方法引用代替的时候,它的形参全部传递给静态方法parseInt()作为参数
//      第二种写法
        System.out.println(((Converter) s -> Integer.parseInt(s)).convert("567"));
        System.out.println(((Converter) Integer::parseInt).convert("567"));
    }

    public static void useConverter(Converter c) {
        int num = c.convert("789");
        System.out.println(num);
    }
}
引用对象的实例方法

实际上是通过对象引用类中的成员方法

package com.xm.方法引用;

interface Printer {
    void printUpperCase(String s);
}

class PrintString {
    public void printUpper(String s) {
        System.out.println(s.toUpperCase());
    }
}

public class Demo3 {
    public static void main(String[] args) {
        usePrinter(s -> System.out.println(s.toUpperCase()));

        PrintString ps = new PrintString();
        usePrinter(ps::printUpper);
        //Lambda表的式被对象的实例方法替代的时候,它的形式参数全部传递给该方法作为参数
    }

    public static void usePrinter(Printer p) {
        p.printUpperCase("helloWorld");

    }
}
引用类的实例方法

实际上是引用类中的成员方法

  • 格式: 类名::成员方法
package com.xm.方法引用;

interface MyString {
    String mySubString(String s, int a, int b);
}

public class Demo4 {
    public static void main(String[] args) {
        int x = 5;
        System.out.println(x);
        useMyString((s, a, b) -> s.substring(a, b));
        useMyString(String::substring);
        // 第一个参数作为调用者
        //后边的参数全部传递给该方法作为参数
        System.out.println(((MyString) (s, a, b) -> s.substring(a, b)).mySubString("helloWorld!!!", 0, 10));
        System.out.println(((MyString) (String::substring)).mySubString("helloWorld!!!", 0, 10));
    }

    public static void useMyString(MyString m) {
        String result = m.mySubString("helloWorld!", 0, 5);
        System.out.println(result);
    }
}

引用构造器

实际上是引用构造方法

格式:类名::new

举例:Student : : new

package com.xm.方法引用;

interface StudentBuilder {
    Student build(String name, int age);
}

class Student {
    private String name;
    private int age;

    public Student() {
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class Demo5 {
    public static void main(String[] args) {
        useStudentBuilder(((name, age) -> new Student(name, age)));
        //引用构造器,Lambda表达式被构造器替代的时候,它的形式参数全部传递给构造器作为参数
        useStudentBuilder(Student::new);
    }

    public static void useStudentBuilder(StudentBuilder sb) {
        System.out.println(sb.build("肖猛", 18).toString());
    }
}

函数式接口

概述

函数式接口:有且仅有一个抽象方法的接口(可以有默认,静态,私有方法),是使用Lambda表达式的前提,是Lambda表达式能够顺利推导的前提;

@FunctionalInterface 注解 放在接口上方,若为函数式接口,则编译通过,否则编译失败

@FunctionalInterface 不加不报错,建议加上该注解;

package com.xm.函数式接口;

@FunctionalInterface
interface MyInterface {
    void show();
    //jdk8
    default void method() {
        show1();
    }
    //jdk8
    static void methods() {
        show1();
    }
    //jdk9
    private static void show1() {
        System.out.println("static---show1");
    }
}

public class Demo1 {
    public static void main(String[] args) {
        //Lambda表达式用做局部变量
        MyInterface my = () -> System.out.println("你好!");
        my.show();
        //回顾接口更新
        my.method();
        MyInterface.methods();
    }
}

函数式接口用作方法的参数

参见方法引用,直接上代码比较直观:

package com.xm.函数式接口;

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "实现类线程启动");
    }
}

public class Demo2 {
    public static void main(String[] args) {
        useRunnable(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "匿名内部类线程启动");
            }
        });
        useRunnable(() -> System.out.println(Thread.currentThread().getName() + "Lambda表达式线程启动"));

        useRunnable(new MyRunnable());

    }

    public static void useRunnable(Runnable r) {
        new Thread(r).start();
    }
}

函数式接口作为方法的返回值

即为Lambda表达式作为返回值

本例中的Comparator是函数式接口

return (…) 返回的类型是Comparator 的实现,所以通过return 语句可以推导出Lambda 表达式的写法(实现Comparator 中的抽象方法);

package com.xm.函数式接口;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Demo3 {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("cccc");
        arrayList.add("aa");
        arrayList.add("b");
        arrayList.add("ddd");
        System.out.println("排序前");
        System.out.println(arrayList);
        Collections.sort(arrayList);
        System.out.println("默认排序");
        System.out.println(arrayList);
        Collections.sort(arrayList, getComparator());
        System.out.println("调用函数式接口作为返回值---按短长排序");
        System.out.println(arrayList);
        Collections.sort(arrayList, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o2.length() - o1.length();
            }
        });
        System.out.println("匿名内部类做参数---按长短排序");
        System.out.println(arrayList);
        Collections.sort(arrayList, (s1, s2) -> s1.length() - s2.length());
        System.out.println("Lambda做参数---按短长排序");
        System.out.println(arrayList);

    }

    public static Comparator<String> getComparator() {
        return (s1, s2) -> s1.length() - s2.length();
//        return new Comparator() {
//            public int compare(String s1, String s2) {
//                return s1.length() - s2.length();
//            }
//        };

    }
}

常用接口

Java8在java.uitl.function包下预定义了大量的函数式接口供我们使用;

1.Supplier接口

Supplier:包含一个无参构造方法

  • T get() :获得结果

  • 该方法不需要参数,他会按照某种逻辑(由Lambda表达式实现)返回一个数据

  • Supplier 接口被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会产生什么类型的数据供我们使用

package com.xm.函数式接口;

import java.util.function.Supplier;

public class Demo4Supplier {
   public static void main(String[] args) {
       String s=(getString(() -> "yes"));
       System.out.println(s);
       System.out.println((getString(() -> "yes")));
       System.out.println(getInteger(()->12345));
   }
   private static Integer  getInteger(Supplier<Integer> supplier)
   {
       return supplier.get();
   }
   private static String  getString(Supplier<String> supplier)
   {
       return supplier.get();
   }
}

test得到数组最大值
package com.xm.函数式接口;

import java.util.function.Supplier;

public class TestSupplier {
    public static void main(String[] args) {
        int [] a= {19, 4, 7, 1, 80, 3};
        int maxValue = getMax(() -> {
            int max = a[0];
            for (int j : a)
                if (j > max)
                    max = j;
            return max;
        });
        System.out.println(maxValue);
    }

    public static Integer getMax(Supplier<Integer> supplier) {
        return supplier.get();
    }
}

2.consumer接口

可以作为Lambda表达式或方法引用的赋值目标

表示接受单个输入参数且不返回结果的操作。 与大多数其他功能接口不同, Consumer预计会通过副作用运行。

  • void accept(T t)
    对给定的参数执行此操作。

  • default Consumer andThen(Consumer after)
    返回一个组合 Consumer ,它按顺序执行此操作,然后执行 after操作。

  • Consumer接口被称消费型接口,如果我们指定了接口的泛型是什么类型,那么接口中的accept方法就会消费什么类型的数据;

package com.xm.函数式接口;

import java.util.function.Consumer;

public class Demo5Consumer {
    public static void main(String[] args) {
        useConsumer((s) -> System.out.println(s));
        useConsumer((s) -> System.out.println(new StringBuilder(s).reverse()));
        ((Consumer<String>) (s) -> System.out.println(s)).accept("what");
        System.out.println("--------------");
        useConsumer("what",(s)->System.out.println(s),(s)->System.out.println(new StringBuilder(s).reverse()));

    }
    public static void useConsumer( String name ,Consumer<String> con,Consumer<String> con2) {
        con.accept(name);
        con2.accept(name);
        System.out.println("-------------");
        con.andThen(con2).accept(name);
    }
    public static void useConsumer(Consumer<String> con) {
        con.accept("what");
    }
}

test按要求打印信息
package com.xm.函数式接口;

import java.util.function.Consumer;

public class TestConsumer {
    public static void main(String[] args) {
        String[] strArray = {"肖猛,18", "李玮晴,18", "刘东旭,6"};
        printConsumer(str -> {
            String name = str.split(",")[0];
            System.out.print(name);
        }, str -> {
            int age = Integer.parseInt(str.split(",")[1]);
            System.out.println(age);
        }, strArray);
    }

    //正常情况是这样,因为我用了可变参数,所以strArray 必须是形参的最后一个;
//  printConsumer(strArray,str->{},str->{}); 
//public static void printConsumer(String... strArray,Consumer con, Consumer con2)    
    public static void printConsumer(Consumer<String> con, Consumer<String> con2, String... strArray) {
        for (String str : strArray) {
            con.andThen(con2).accept(str);
        } 
    }
}

3.Predicate接口

Predicate接口实际上是谓语匹配

方法:test(T t) 参数T: 输入参数 返回: true如果输入参数与谓词匹配,否则为 false

  • default Predicate and(Predicate other)
    返回一个组合谓词,表示此谓词和另一个谓词的短路逻辑AND。

  • static Predicate isEqual(Object targetRef)
    返回一个谓词,根据 Objects.equals(Object, Object)测试两个参数是否相等。

  • default Predicate negate()
    返回表示此谓词的逻辑否定的谓词。

  • default Predicate or(Predicate other)
    返回一个组合谓词,表示此谓词与另一个谓词的短路逻辑OR。

  • boolean test(T t)
    根据给定的参数计算此谓词。

package com.xm.函数式接口;

import java.util.function.Predicate;

public class Demo6Predicate {
    public static void main(String[] args) {
        //1.test
        boolean b1 = checkString("hello", w -> w.length() >= 8);
        System.out.println(b1);
        boolean b2 = checkString("helloWorld", w -> w.length() >= 8);
        System.out.println(b2);
        //3.and 与
        boolean b3 = checkString("hello", s -> s.length() > 29, s -> s.equals("hello"));
        System.out.println(b3);
        //4.or 或
        boolean b4 = CheckString("hello", s -> s.length() > 4, s -> s.equals("hello"));
        System.out.println(b4);
    }

    //1.test
    //判断字符串是否满足条件
    public static boolean checkString(String s, Predicate<String> predicate) {
//        return predicate.test(s);正常判断
//      2.negate(),逻辑非;
//      return !predicate.test(s);
        return predicate.negate().test(s);
    }

    //3.and 与
    //同一个字符串给出两个不同的判断条件,最后把这两个判断的条件做逻辑与运算的结果作为最终的结果
    public static boolean checkString(String s, Predicate<String> predicate, Predicate<String> predicate2) {
//        boolean b1=predicate.test(s);
//        boolean b2=predicate2.test(s);
//        boolean b=b1&&b2;
//        return b;
        return predicate.and(predicate2).test(s);
    }

    //4.or或
    public static boolean CheckString(String s, Predicate<String> predicate, Predicate<String> predicate2) {
//        boolean b1 = predicate.test(s);
//        boolean b2 = predicate2.test(s);
//        boolean b = b1 || b2;
//        return b;
        return predicate.or(predicate2).test(s);
    }


}

test筛选条件

条件:年龄字符大于2,年龄大于8的数据放入ArrayList 并遍历

package com.xm.函数式接口;

import java.util.ArrayList;
import java.util.function.Predicate;

//筛选条件,年龄字符大于2,年龄大于8;的数据放入ArrayList 并遍历
public class TestPredicate {
    public static void main(String[] args) {
        String[] strArray = {"肖猛,18", "李玮晴,10", "刘东旭,6"};
        ArrayList<String> array = new ArrayList<>();
        Check(strArray, array, s -> s.split(",")[0].length() > 2, s -> Integer.parseInt(s.split(",")[1]) > 8);
    }

    public static void Check(String[] strArray, ArrayList<String> array, Predicate<String> predicate, Predicate<String> predicate2) {
        for (String str : strArray) {
            if (predicate.and(predicate2).test(str))
                array.add(str);
        }
        for (String string : array)
            System.out.println(string);
    }

}

4.Function接口

Function(T,R) 表示接受一个参数并生成结果的函数。
这是functional interface,其功能方法是apply(Object) 。

T - 函数输入的类型

R - 函数结果的类型

  • default Function andThen(Function after) 返回首先将此函数应用于其输入的 after函数,然后将 after函数应用于结果。
  • R apply(T t) 将此函数应用于给定的参数。
package com.xm.函数式接口;

import java.util.function.Function;

public class Demo7Function {
    public static void main(String[] args) {
        Integer integer = convert("12345", s -> {d
            return Integer.parseInt(s);
        });
        System.out.println("String--->Integer类型:" + integer);
// 有返回值的接口方法,Lambda表达式调用方法,会产生返回值,具体接收看情况而定
        convertString(2345, i -> {
            int x = 10000;
            return String.valueOf(i + x);
        });

        String s1 = convertPlus("345", s -> Integer.parseInt(s), i -> String.valueOf(i + 12000));
        System.out.println("String--->int--->String:" + s1);
    }

    //String 类型转化为Integer类型
    public static Integer convert(String s, Function<String, Integer> f) {
        return f.apply(s);
    }

    //int 类型加一个整数,转化为String类型
    public static void convertString(int i, Function<Integer, String> f) {
        String s = f.apply(i);
        System.out.println("Integer--->字符串类型:" + s);
    }

    //把一个字符串转化为int 类型,加上一个整数后,转为字符串输出
    public static String convertPlus(String s, Function<String, Integer> f, Function<Integer, String> f2) {
//        int i=f.apply(s);
//        String ss=f2.apply(i);
//        return ss;
        return f.andThen(f2).apply(s);
    }
}

计算肖猛真实年龄

假设:String s=“肖猛,20”;

要求:

  1. 将字符串截取,得到数字年龄部分
  2. 将数字年龄部分转化为int类型的数据
  3. 将上部int型的年龄减去2,得到一个int结果就是肖猛真实年龄,在控制台输出
package com.xm.函数式接口;

import java.util.function.Function;

public class TestFunction {
    public static void main(String[] args) {
        System.out.println("盲猜肖猛年龄为20");
        int answer = convertFunction("肖猛,20", s -> Integer.parseInt(s.split(",")[1]) - 2);
        System.out.println("肖猛的真实年龄:" + answer);
    }

    public static int convertFunction(String s, Function<String, Integer> f) {
        return f.apply(s);
    }
}

Stream流

体验Stream流

Stream 流把真正的函数式编程风格引入Java中

筛选学生

package com.xm.Stream;

import java.util.ArrayList;

public class Demo1 {
    public static void main(String[] args) {
        ArrayList<String> array = new ArrayList<>();
        ArrayList<String> array1 = new ArrayList<>();
        ArrayList<String> array2 = new ArrayList<>();
        array.add("肖猛");
        array.add("肖限量");
        array.add("李肥肥");
        array.add("肖扬1");
        for (String name : array) {
            if (name.charAt(0) == '肖') {
                array1.add(name);
                if (name.length() == 3)
                    array2.add(name);
            }
        }
        for (String name3 : array2)
            System.out.println(name3);
        System.out.println("-----------");
//        array.stream().filter(s -> s.startsWith("肖")).filter(s -> s.length() == 3).forEach(System.out::println);
        array.stream().filter(s -> s.startsWith("肖")).filter(s -> s.length() == 3).forEach(s -> System.out.println(s));


    }
}

Stream流的生成方式
  1. Collection 体系(Set,List的集合可以使用默认方法stream() 生成流
  2. Map体系的集合间接的生成流
  3. 数组可以通过Stream 接口的静态方法of (T … values)生成流
package com.xm.Stream;

import java.util.*;
import java.util.stream.Stream;

public class Demo2 {
    public static void main(String[] args) {
        //1.Collection 体系(Set,List的集合可以使用默认方法Stream() 生成流
        ArrayList<String> arrayList=new ArrayList<>();
        arrayList.add("1");
        arrayList.add("12");
        arrayList.add("123");
        arrayList.add("1234");
        arrayList.add("12345");
        arrayList.add("123456");
        Stream<String> arrayStream = arrayList.stream();
        
        //2.Map体系的集合间接的生成流
        Map<String,Integer> map=new HashMap<>();
        //键的Stream流
        Stream<String> keyStream = map.keySet().stream();
        //值的Stream流
        Stream<Integer> valueStream = map.values().stream();
        //键值对的Stream流
        Stream<Map.Entry<String, Integer>> mapStream = map.entrySet().stream();
        
        // 数组的Stream流
        String []str={"你好","你也好","都挺好"};
        Stream<String> strStream = Stream.of(str);
        Stream<Integer> integerStream = Stream.of(10, 20, 30);


    }
}

1.Stream流中间操作filter,limit,skip concate,distinct

Streamfilter (Predicate predicate):用于对流中的数据进行过滤

Predicate 接口中的方法 boolean test(T t) :对给定的参数进行判断,返回布尔值;

Stream limit(long maxSize) :返回此流中的元素组成的流,截取前指定参数个数的数据

Streamskip(long n):跳过指定个数的数据,返回有该流的剩余元素组成的流

staticStreamconcat(Stream a,Stream b):合并a和b两个流为一个流

StreamDistinct():返回由该流的不同元素(根据Object.equals(Object))组成的流 底层实现:equal方法;

package com.xm.Stream;

import java.util.ArrayList;
import java.util.stream.Stream;

public class Demo3 {
    public static void main(String[] args) {
        ArrayList<String> array = new ArrayList<>();
        array.add("肖彦斌");
        array.add("肖限量");
        array.add("李肥肥");
        array.add("肖扬1");
        array.add("肖志强");
        
        //filter    过滤
        array.stream().filter(s->s.startsWith("肖")).filter(s -> s.length()==3).forEach(s->System.out.println(s));
        System.out.println("-------");
        
        //limit   返回前N 个数据组成的流
        Stream<String> limit = array.stream().limit(3);
        array.stream().limit(3).forEach(System.out::println);
        System.out.println("-------");
        
        //skip 跳过 前N个数据,返回 剩余数据组成的流
        Stream<String> skip = array.stream().skip(2);
        array.stream().skip(2).forEach(System.out::println);
        System.out.println("-------");
        
        //concat Stream流合并
//        Stream.concat(limit,skip).forEach(System.out::println);
//        Stream.concat(array.stream().limit(3),array.stream().skip(2)).forEach(System.out::println);
        
        //distinct 返回由该流的不同元素(根据Object.equals(Object))组成的流 底层实现:equal方法;
        System.out.println("what");
        Stream.concat(limit,skip).distinct().forEach(System.out::println);
    }
}

2.Stream流中间操作sorted()

Streamsorted():返回由此流的元素组成的流,根据自然顺序排序

Streamstored(Comparator comparator):返回由该流的元素组成的流,根据提供的Comparator进行排序

package com.xm.Stream;

import java.util.ArrayList;
import java.util.Collections;

public class Demo4 {
    public static void main(String[] args) {
        ArrayList<String > list=new ArrayList<>();
        list.add("bbb");
        list.add("aaaa");
        list.add("aaac");
        list.add("aaab");
        list.add("c");
        Collections.sort(list);
        Collections.sort(list,(s1,s2)->s1.length()-s2.length());
        for(String s:list)
            System.out.println(s);
        list.stream().sorted().forEach(System.out::println);
        list.stream().sorted((s1,s2)->s1.length()-s2.length()).forEach(System.out::println);
        list.stream().sorted((s1,s2)->{
            int num1=s1.length()-s2.length();
            return num1==0?s1.compareTo(s2):num1;}
        ).forEach(System.out::println);
    }
}

3.Stream流中间操作map,mapToInt

Streammap(Function mapper) :返回由给定函数应用于此流的元素的结果组成的流 Function 接口中的方法 R apply(T t);

IntStream mapToInt (ToIntFunction mapper):返回一个IntStream其中包含将给定函数应用于此流的元素的结果。

package com.xm.Stream;

import java.util.ArrayList;
import java.util.stream.IntStream;

public class Demo5 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("10");
        list.add("20");
        list.add("30");
        list.add("40");
        //map   将字符串数据转化为整数之后在控制台输出
        list.stream().map(Integer::parseInt).forEach(System.out::println);
        //list.stream().map(s -> Integer.parseInt(s)).forEach(s->System.out.println(s));

        //mapToInt
        // sum方法返回 IntStream 中的数值总和;
        IntStream intStream = list.stream().mapToInt(Integer::parseInt);
        int sum = intStream.sum();
        System.out.println(sum);
    }
}

4.Stream流终结操作forEach,count

void ForEach(Consumer action):对此流的每一个元素执行操作 Consumer接口中的方法 void accept(T t):对给定的参数执行此操作

long count() :返回此流中的元素个数

package com.xm.Stream;

import java.util.ArrayList;

public class Demo5 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("10");
        list.add("20");
        list.add("30");
        list.add("40");
        // forEach
        list.stream().forEach(System.out::println);
        //count
        long count = list.stream().count();
        System.out.println(count);

6.Stream流的收集操作
  • R collect(Collector collector) 该收集方法的参数是一个Collector接口

工具类Collectors提供了具体的收集方式

  • public static Collector toList():把元素收集到List集合中
  • public static Collector toSet():把元素收集到Set集合中
  • public static Collector toMap(Function keyMapper,Function valueMapper):把元素收集到Map集合
package com.xm.Stream;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Demo7 {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("李肥肥");
        arrayList.add("肖一");
        arrayList.add("动见");
        arrayList.add("曾国藩");
        arrayList.add("左宗棠");
        List<String> list = arrayList.stream().filter(s -> s.length() == 3).collect(Collectors.toList());
        for (String s : list)
            System.out.println(s);
        Set<Integer> hashSet = new HashSet<>();
        hashSet.add(10);
        hashSet.add(20);
        hashSet.add(30);
        hashSet.add(40);
        hashSet.add(50);
        hashSet.add(6000_000);
        Set<Integer> set = hashSet.stream().filter(s -> s >= 40).collect(Collectors.toSet());
        for (Integer i : set)
            System.out.println(i);

        String[] str = {"肖猛,18", "李肥肥,18", "刘东旭,8", "小透明,7"};
        Stream<String> strStream = Stream.of(str).filter(s -> Integer.parseInt(s.split(",")[1]) > 10);
        Map<String, Integer> map = strStream.collect(Collectors.toMap(s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1])));
        //遍历1
        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        for (Map.Entry<String, Integer> element : entries) {
            System.out.println(element.getKey() + element.getValue());
        }
        System.out.println("-----------------");
        //遍历2
        Set<String> keySet = map.keySet();
        for(String key:keySet) {
            System.out.println(key+map.get(key));
        }


    }
}

Stream流综合练习

现在要有ArrayList集合,分别储存5名男生和5名女生,要求完成如下的操作

男生只要名字为3个字的前3人

女生只要姓林的,并且不要第一个

把过滤后的男生姓名和女生姓名合并到一起

把上一步操作后的元素作为构造方法的参数创建性别对象,遍历数据Person类已经提供,里面有一个成员变量,一个带参构造方法,已经成员变量对应的get/set方法

package com.xm.Stream;

import java.util.ArrayList;
import java.util.stream.Stream;

public class Demo6 {
    public static void main(String[] args) {
        ArrayList<String>  boyList=new ArrayList<>();
        boyList.add("李肥肥");
        boyList.add("肖一");
        boyList.add("动见");
        boyList.add("曾国藩");
        boyList.add("左宗棠");
        ArrayList<String> girlList=new ArrayList<>();
        girlList.add("窦漪房");
        girlList.add("肖涵");
        girlList.add("武则天");
        girlList.add("肖允许");
        girlList.add("小透明");
        ArrayList<Person> peopleList=new ArrayList<>();
        Stream<String> boy = boyList.stream().filter(s -> s.length() == 3).limit(3);
        Stream<String> girl=girlList.stream().filter(s->s.startsWith("肖")).skip(1);//先把肖挑选出来组成新流,再从中跳过第一个;
//        Stream.concat(boy,girl).forEach(s-> peopleList.add(new Person(s)));
//        for(Person person:peopleList)
//            System.out.println(person);
        Stream<String> stream = Stream.concat(boy, girl);
        Stream<Person> personStream = stream.map(s -> new Person(s));
        personStream.forEach(System.out::println);

    }
}
class Person{
    private String name;

    public Person(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }

    public Person(){}
}

你可能感兴趣的:(JavaSE,java,开发语言)