函数式接口与Stream流

lambda表达式是jdk8的特性.lambda表达式的准则是:可推断,可省略.

常规代码写一个多线程

public class Main {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("run ");
            }
        }).start();
    }
}

lambda表达式写一个多线程

public class Main {
    public static void main(String[] args) {
        new Thread(() -> System.out.println("run")).start();
    }
}

lambda表达式的使用限制是.只能用来代替一个接口的方法.

自定义一个带参数的接口方法

public interface Person {
    public void show(String name);
}
public class Main {
    public static void main(String[] args) {
        personShow((String name) -> {
            System.out.println(name);
        }, "张三");
    }

    public static void personShow(Person p, String name) {
        p.show(name);
    }
}

lambda表达式语法分为两部分, 左边为参数,->右边为方法体.方法参数可以不指定类型,方法体如果只有一句可以省略大括号,省略return关键字.因为类型推断的原因,原则是能省就剩.

关于lambda表达式jdk8产生了一个新的注解@FunctionalInterface被这个注解修饰的接口,只能有一个抽象方法.称之为函数式接口.属于一个标记性接口,但是他对接口本身又有抽象方法个数的限制

JDK8内置的4个常用函数式接口

Consumer<T>:消费型接口 void accpet(T t);

public class Test1 {
    public static void main(String[] args) {
        Test1 test1 = new Test1();
        test1.happy(1000,(m)-> System.out.println("您当前消费"+m+"元"));
    }

    public void happy(double money, Consumer<Double> con) {
        con.accept(money);
    }
}

Supplier<T>:供给型接口 T get();

public class Test1 {
    public static void main(String[] args) {
        Test1 test1 = new Test1();
        List list = test1.getNumList(5, () -> {
            return 1;
        });
        System.out.println(list.size());
    }

    public List<Integer> getNumList(int num, Supplier<Integer> sup) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            list.add(sup.get());
        }
        return list;
    }
}

Fucntion<T,R>:函数型接口 R apply(T t);

public class Test1 {
    public static void main(String[] args) {
        Test1 test1 = new Test1();
        String hehe = test1.strHandler("hehe", (s) -> s.toUpperCase());
        System.out.println(hehe);
    }

    public String strHandler(String str, Function <String,String> f){
        return f.apply(str);
    }
}

Predicate<T>:断言型接口 boolean test(T t);

public class Test1 {
    public static void main(String[] args) {
        Test1 test1 = new Test1();
        boolean b = test1.is(1, (s) -> s > 3);
        System.out.println(b);
    }

    public boolean is(int n, Predicate<Integer> p) {
        return p.test(n);
    }
}

像这类的函数式接口定义的原因只是为了在我们需要自定义函数式接口时,可以使用定义好的函数式接口.

Stream流

先把源数据(集合只能是Collection集合,数组)变成流,然后对流中的数据进行操作,然后产生一个新的流.不会改变源数据.

public class Employee {
    private String name;
    private Integer age;
    private Double pay;

    public Employee(String name, Integer age, Double pay) {
        this.name = name;
        this.age = age;
        this.pay = pay;
    }

    public String getName() {
        return name;
    }

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

    public Integer getAge() {
        return age;
    }

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

    public Double getPay() {
        return pay;
    }

    public void setPay(Double pay) {
        this.pay = pay;
    }

    @Override
    public String toString() {
        return "Employee{" +
                "name=‘" + name + ‘\‘‘ +
                ", age=" + age +
                ", pay=" + pay +
                ‘}‘;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return Objects.equals(name, employee.name) &&
                Objects.equals(age, employee.age) &&
                Objects.equals(pay, employee.pay);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, pay);
    }
}
public class Test {
    public static void main(String[] args) {
        //集合获取流
        List<String> list = new ArrayList<>();
        Stream<String> stream = list.stream();
        Stream<String> stringStream = list.parallelStream();

        //数组获取流,Stream IntStream LongStream 都继承自BaseStream
        Stream<String> stream1 = Arrays.stream(new String[10]);
        IntStream stream2 = Arrays.stream(new int[10]);
        LongStream stream3 = Arrays.stream(new long[10]);
    }
}

筛选与切片

filter--接收lambda,从流中排除某些元素

public class Test2 {
    public static void main(String[] args) {
        //创建源数据
        List<Employee> employees = Arrays.asList(
                new Employee("张十八", 18, 9999.99),
                new Employee("张五十八", 58, 5555.55),
                new Employee("张二十六", 26, 3333.33),
                new Employee("张三十六", 36, 6666.66),
                new Employee("张十二", 12, 8888.88));

        //转换成流,对流中的数据进行过滤操作
        Stream<Employee> employeeStream = employees.stream()
                .filter((e) -> e.getAge() > 18);

        //终止操作     //注意终止操作不可做两次,本身意义就像是,一个桶里装满了水,当我们终止操作相当于将水倒了出来,是不能进行重复操作的.      employeeStream.forEach((x)-> System.out.println(x));
    }
}
Employee{name=‘张五十八‘, age=58, pay=5555.55}
Employee{name=‘张二十六‘, age=26, pay=3333.33}
Employee{name=‘张三十六‘, age=36, pay=6666.66}

limit--截断流,使其元素不超过给定数量

public class Test2 {
    public static void main(String[] args) {
        //创建源数据
        List<Employee> employees = Arrays.asList(
                new Employee("张十八", 18, 9999.99),
                new Employee("张五十八", 58, 5555.55),
                new Employee("张二十六", 26, 3333.33),
                new Employee("张三十六", 36, 6666.66),
                new Employee("张十二", 12, 8888.88));

        //转换成流,对流中的数据进行过滤操作
        Stream<Employee> employeeStream = employees.stream()
                .limit(2);

        //终止操作
        employeeStream.forEach((x)-> System.out.println(x));
    }
}
Employee{name=‘张十八‘, age=18, pay=9999.99}
Employee{name=‘张五十八‘, age=58, pay=5555.55}

skip(n)--跳过元素,返回一个扔掉了前n个元素的流,若流中的元素不足n个,则返回一个空流,与limit(n)互补

public class Test2 {
    public static void main(String[] args) {
        //创建源数据
        List<Employee> employees = Arrays.asList(
                new Employee("张十八", 18, 9999.99),
                new Employee("张五十八", 58, 5555.55),
                new Employee("张二十六", 26, 3333.33),
                new Employee("张三十六", 36, 6666.66),
                new Employee("张十二", 12, 8888.88));

        //转换成流,对流中的数据进行过滤操作
        Stream<Employee> employeeStream = employees.stream()
                .skip(2);

        //终止操作
        employeeStream.forEach((x)-> System.out.println(x));
    }
}
Employee{name=‘张二十六‘, age=26, pay=3333.33}
Employee{name=‘张三十六‘, age=36, pay=6666.66}
Employee{name=‘张十二‘, age=12, pay=8888.88}

distinct--筛选,通过流所产生的hashCode()和equals()去除重复元素

public class Test2 {
    public static void main(String[] args) {
        //创建源数据
        List<Employee> employees = Arrays.asList(
                new Employee("张十八", 18, 9999.99),
                new Employee("张十八", 18, 9999.99),
                new Employee("张十八", 18, 9999.99),
                new Employee("张五十八", 58, 5555.55),
                new Employee("张二十六", 26, 3333.33),
                new Employee("张三十六", 36, 6666.66),
                new Employee("张十二", 12, 8888.88));

        //转换成流,对流中的数据进行过滤操作
        Stream<Employee> employeeStream = employees.stream()
                .distinct();

        //终止操作
        employeeStream.forEach((x)-> System.out.println(x));
    }
}
Employee{name=‘张十八‘, age=18, pay=9999.99}
Employee{name=‘张五十八‘, age=58, pay=5555.55}
Employee{name=‘张二十六‘, age=26, pay=3333.33}
Employee{name=‘张三十六‘, age=36, pay=6666.66}
Employee{name=‘张十二‘, age=12, pay=8888.88}

映射

map--接收lambda,对流中的每一个记录都进行操作,然后将操作的返回值,从新读取到一个新的流中,注意这个map是有返回值的.我之所以会写上return 和{} 就是为了显示map产生的新流只是返回值的结果集合

public class Test3 {
    public static void main(String[] args) {
        //创建源数据
        List<Employee> employees = Arrays.asList(
                new Employee("张十八", 18, 9999.99),
                new Employee("张五十八", 58, 5555.55),
                new Employee("张二十六", 26, 3333.33),
                new Employee("张三十六", 36, 6666.66),
                new Employee("张十二", 12, 8888.88));

        employees.stream()
                .map((e) -> {
                    return e.getPay().intValue();
                })
                .forEach((e) -> System.out.println(e));
    }
}

flatMap--接收一个函数作为参数,将流中的每个值都转换成另一个流,然后把所有流都连接成一个流

public class Test3 {
    public static void main(String[] args) {
        List<String> arrayList = Arrays.asList("a", "b", "c", "d");

        //当一个流的元素还是流
        Stream<Stream<Character>> streamStream = arrayList.stream().map((e) -> filterCharacter(e));
        //双重forEach
        streamStream.forEach((e) -> {
            e.forEach((i) -> System.out.println(i));
        });

        System.out.println("-----------------------------");
        //使用flatMap可以将多个流直接转换成一个流
        Stream<Character> characterStream = arrayList.stream().flatMap((e) -> filterCharacter(e));
        characterStream.forEach((e) -> {
            System.out.println(e);
        });

    }

    public static Stream<Character> filterCharacter(String str) {
        List<Character> list = new ArrayList<>();
        for (Character ch : str.toCharArray()) {
            list.add(ch);
        }
        return list.stream();
    }
}
a
b
c
d
-----------------------------
a
b
c
d

排序

sorted()自然排序

public class Test4 {
    public static void main(String[] args) {
        List<String> arrayList = Arrays.asList("b","a","c");
        arrayList.stream()
                .sorted()
                .forEach((e)-> System.out.println(e));
    }
}
a
b
c

sorted(Comparator com)定制排序

public class Test4 {
    public static void main(String[] args) {
        //创建源数据
        List<Employee> employees = Arrays.asList(
                new Employee("张十八", 18, 9999.99),
                new Employee("张五十八", 58, 5555.55),
                new Employee("张二十六", 26, 3333.33),
                new Employee("张三十六", 36, 6666.66),
                new Employee("张十二", 12, 8888.88));
        employees.stream()
                .sorted((e1, e2) -> {
                    return e1.getPay().compareTo(e2.getPay());
                })
                .forEach((e) -> System.out.println(e));
    }
}
Employee{name=‘张二十六‘, age=26, pay=3333.33}
Employee{name=‘张五十八‘, age=58, pay=5555.55}
Employee{name=‘张三十六‘, age=36, pay=6666.66}
Employee{name=‘张十二‘, age=12, pay=8888.88}
Employee{name=‘张十八‘, age=18, pay=9999.99}

我们对stream流中的数据进行操作,最终都有一个停止操作.与其说是停止操作,不如说是你要这个流最终干什么.我们也看到了,不管我们做切割,筛选等操作,最终返回的还是一个stream流,所以我们将stream流最终

变成我们需要的数据就是终止操作,以上我们用的forEach就是停止操作,尽管他没有返回值

查找与匹配

allMatch--检查是否匹配所有元素

public class Test5 {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3);
        boolean b = list.stream()
                .allMatch((e) -> e == 1);
        System.out.println(b);//false
    }
}

anyMatch--检查是否至少匹配一个元素

public class Test5 {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3);
        boolean b = list.stream()
                .anyMatch((e) -> e == 1);
        System.out.println(b);//true
    }
}

noneMatch--检查是否没有匹配所有元素

public class Test5 {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3);
        boolean b = list.stream()
                .noneMatch((e) -> e == 1);
        System.out.println(b);//false
    }
}

findFirst--返回当前流中的第一个元素

public class Test5 {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3);
        Optional<Integer> first = list.stream()
                .findFirst();    //注意,此时返回的是一个Optional,这个是JDK8为了避免null而封装的一个对象
        System.out.println(first.get());//1
    }
}

findAny--返回流中的任意元素

public class Test5 {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3);     //其实就是随机返回了一个,但是为了演示明显这里使用了串行流,也就是多线程.
        Optional<Integer> first = list.parallelStream()
                .findAny();
        System.out.println(first.get());//2
    }
}

count--返回流中的总个数

public class Test5 {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3);
        long count = list.parallelStream()
                .count();
        System.out.println(count);//3
    }
}

max--返回流中的最大值

public class Test5 {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3);
        Optional<Integer> max = list.parallelStream()
                .max((x, y) -> Integer.compare(x, y));
        System.out.println(max.get());//3
    }
}

min--返回流中的最小值

public class Test5 {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3);
        Optional<Integer> max = list.parallelStream()
                .min((x, y) -> Integer.compare(x, y));
        System.out.println(max.get());//1
    }
}

收集元素,将流中的数据转换成集合

public class Test5 {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3,4,5,6);
        List<Integer> collect = list.stream()
                .limit(2)
                .collect(Collectors.toList());
        System.out.println(collect.size());
    }
}
public class Test5 {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3,4,5,6);
        LinkedHashSet<Integer> collect = list.stream()
                .limit(2)
                .collect(Collectors.toCollection(LinkedHashSet::new));
        System.out.println(collect.size());
    }
}

原文地址:https://www.cnblogs.com/zumengjie/p/11613043.html

时间: 2024-10-10 20:08:36

函数式接口与Stream流的相关文章

常用函数式接口与Stream API简单讲解

常用函数式接口与Stream API简单讲解 Stream简直不要太好使啊!!! 常用函数式接口 Supplier<T>,主要方法:T get(),这是一个生产者,可以提供一个T对象. Consumer<T>,主要方法:void accept(T),这是一个消费者,默认方法:andthen(),稍后执行. Predicate<T>,主要方法:boolean test(T t),这是一个判断者,默认方法:and():且,or():或,negate():非. Functio

Java8函数式编程(二):类比Spark RDD算子的Stream流操作

1 Stream流 对集合进行迭代时,可调用其iterator方法,返回一个iterator对象,之后便可以通过该iterator对象遍历集合中的元素,这被称为外部迭代(for循环本身正是封装了其的语法糖),其示意图如下: 除此之外,还有内部迭代方法,这正是这里要说明的集合的stream()方法返回的Stream对象的一系列操作,比如,要统计一个数字列表的偶数元素个数,当使用Stream对象的操作时,如下: List<Integer> list = new ArrayList<Integ

乐字节-Java8新特性-接口默认方法之Stream流(下)

接上一篇:<Java8新特性之stream>,下面继续接着讲Stream 5.流的中间操作 常见的流的中间操作,归为以下三大类:筛选和切片流操作.元素映射操作.元素排序操作: 操作 描述 筛选和切片 filter(T -> boolean):保留 boolean 为 true 的元素 limit(long n):返回前 n 个元素 skip(long n):去除前 n 个元素 distinct():去除重复元素,这个方法是通过类的 equals 方法来判断两个元素是否相等的 映射 map

Java之函数式接口

函数式接口 概述:接口中只有一个抽象方法 下面介绍的可能很抽象,理解不了,至少在我看来单独的这几个借口是没有用的,跟最下面说的 Stream流一起用才会有效果 函数式接口,即适用于函数式编程场景的接口.而Java中的函数式编程体现就是Lambda,所以函数式接口就是可 以适用于Lambda使用的接口.只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导. 备注:"语法糖"是指使用更加方便,但是原理不变的代码语法.例如在遍历集合时使用的for-each语法,其实

009-jdk1.8版本新特性一-展方法,Lambda表达式,函数式接口、方法引用构造引用

一.JDK1.8 名称:Spider(蜘蛛) 发布日期:2014-03-18 新特性: 1.1.扩展方法[接口的默认方法] Java 8允许我们给接口添加一个非抽象的方法实现,只需要使用 default关键字即可,这个特征又叫做扩展方法. 在Java中只有单继承,如果要让一个类赋予新的特性,通常是使用接口来实现,在C++中支持多继承,允许一个子类同时具有多个父类的接口与功能,在其他语言中,让一个类同时具有其他的可复用代码的方法叫做mixin.新的Java 8 的这个特新在编译器实现的角度上来说更

Stream流

Stream流 stream流,是在java8中,由lambda表达式所带来的一种新的函数是编程模式,可以用来解决一些已有的集合类型的弊端. 1.stream流与传统集合的便利方式的区别 传统遍历方式 1 public static void main(String[] args) { 2 //遍历输出名字中含有七的并且名字长度为3的人 3 List<String> list = List.of("乔七七","韩七岁","零零七",&

java8 stream流操作

Stream 在对流进行处理时,不同的流操作以级联的方式形成处理流水线.一个流水线由一个源(source),0 到多个中间操作(intermediate operation)和一个终结操作(terminal operation)完成. 源:源是流中元素的来源.Java 提供了很多内置的源,包括数组.集合.生成函数和 I/O 通道等. 中间操作:中间操作在一个流上进行操作,返回结果是一个新的流.这些操作是延迟执行的. 终结操作:终结操作遍历流来产生一个结果或是副作用.在一个流上执行终结操作之后,该

乐字节-Java8核心特性实战之函数式接口

什么时候可以使用Lambda?通常Lambda表达式是用在函数式接口上使用的.从Java8开始引入了函数式接口,其说明比较简单:函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口. java8引入@FunctionalInterface 注解声明该接口是一个函数式接口. 语法 抽象方法有且仅有一个 接口使用@FunctionalInterface 注解进行标注 接口中可以存在默认方法和静态方法实现 如下形式: /** * 定义函数式

java中的Stream流

java中的Stream流 说到Stream便容易想到I/O Stream,而实际上,谁规定"流"就一定是"IO流"呢?在Java 8中,得益于Lambda所带 来的函数式编程,引入了一个全新的Stream概念,用于解决已有集合类库既有的弊端. 一.引言 传统集合的多步遍历代码 几乎所有的集合(如 Collection 接口或 Map 接口等)都支持直接或间接的遍历操作.而当我们需要对集合中的元 素进行操作的时候,除了必需的添加.删除.获取外,典型的就是集合遍历.