java中的方法引用和Stream流

知识模块:
一.方法引用
         a.方法概述
         b.方法引用格式
二.Stream流
         1.Stream流概述
         2.Stream流操作步骤




一.方法引用
   a.方法概述
      /*
        方法引用概述:
          当我们使用已有类中的方法作为Lambda表达式对应的接口中的抽象方法实现
          我们可以用方法引用来简化Lambda表达式

       */

import org.junit.Test;

import java.util.function.Consumer;

/*
  方法引用概述:
    当我们使用已有类中的方法作为Lambda表达式对应的接口中的抽象方法实现
    我们可以用方法引用来简化Lambda表达式

 */
public class MethodRef01 {
    @Test
    public void test01() {
        Consumer<String> c = str -> System.out.println(str);
        c.accept("abc");

        System.out.println(System.out);//java.io.PrintStream@f5f2bb7
    }
    @Test
    public void test02() {
        //Consumer<String> c = str -> System.out.println(str);
        Consumer<String>c=System.out::println; //System.out代表了我们要引用的类
                                               //::后面的println代表我们引用的方法
        c.accept("abc");


    }

}
/*


  class MethodRefDemo$$Lambda$1 implements Consumer<sTRING>{
      public void accept(String str){
        System.out.println(str);//我们使用是PrintStream类中的println(String str)方法
                                //作为str->System.out.println(str)对应的Consumer<String>
                                //中accept(String str)的实现
      }
  }


 */
   b.方法引用格式
    方法引用使用的前提:(适用于1,2)
          引用的方法和Lambda表达式对应接口中的抽象方法中的形参类型保持一致
      1.成员方法引用
         a.引用非静态成员方法
               /*

                 非静态成员引用
                    对象名::方法名

                */

import java.util.Objects;

public class Person {
    private String name;

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

    public String getName() {
        return name;
    }

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

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Person person)) return false;
        return name.equals(person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name);
    }
}

import org.junit.Test;

import java.util.function.Consumer;
import java.util.function.Supplier;

/*
 方法引用使用的前提:
     引用的方法和Lambda表达式对应接口中的抽象方法中的形参类型保持一致
  非静态成员引用
     对象名::方法名

 */
public class MethodRefDemo02 {
    Person p = new Person("老王");
    @Test
    public void test01() {

        //Supplier<String >s=()->p.getName();
        Supplier<String> s = p::getName;
        System.out.println(s.get());
    }
    @Test
    public void test02() {
        //Consumer<String> c = name -> p.setName(name);
        Consumer<String>c=p::setName;
        c.accept("老李");
        System.out.println(p);
    }

    @Test
    public void test03() {
        String str = "abc";
        //Supplier<Integer> s = () -> str.length();
        Supplier<Integer> s = str::length;
        System.out.println(s.get());
    }
    @Test
    public void test04() {
        String str = "abc";


        //Supplier<Character> s = () -> str.charAt(1);

       /* Supplier<Character>s=str::charAt;  //一个有参,一个无参,不能简化
        System.out.println(s.get());*/
    }
}
         b.引用静态成员方法
               /*
                 静态方法引用
                    类名::静态方法名
                    Arrays,Collections
                    Arrays类中
                        static String toString(int[] a)
                               返回指定数组内容的字符串表示形式。
                    Collections类
                        public static <T extends Comparable<? super T>> void sort(List<T> list)
                              根据元素的自然顺序 对指定列表按升序进行排序
                */

import org.junit.Test;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;

/*
  静态方法引用
     类名::静态方法名
     Arrays,Collections
     Arrays类中
         static String toString(int[] a)
                返回指定数组内容的字符串表示形式。
     Collections类
         public static <T extends Comparable<? super T>> void sort(List<T> list)
               根据元素的自然顺序 对指定列表按升序进行排序
 */
public class MethodRefDemo03 {
    @Test
    public void test01() {
        int[] arr = {3, 7, 9};
        //Function<int[], String> f = array -> Arrays.toString(array);
        Function<int[],String>f=Arrays::toString;
        System.out.println(f.apply(arr));
    }

    @Test
    public void test02() {
        List<Integer> integers = Arrays.asList(1, 7, 12, 5, 23);
        //Consumer<List<Integer>> c = list -> Collections.sort(list);
        Consumer<List<Integer>> c = Collections::sort;

        c.accept(integers);

        System.out.println(integers);
    }
}
      2.构造方法引用
               /*
                 构造方法引用格式:
                    类名::new

               */
      3.数组对象引用
                数组对象引用格式
                     类型[]::new

import org.junit.Test;

import java.util.function.Function;

/*
  构造方法引用格式:
     类名::new
  数组对象引用格式
     类型[]::new
 */
public class MethodRefDemo04 {
    @Test
    public void test01() {
        //创建一个Person类的对象,获取这个对象
        //Function<String, Person> f = name -> new Person(name);
        Function<String, Person> f = Person::new;
        System.out.println(f.apply("三丰"));
    }
    @Test
    public void test02() {
        //创建一个指定长度的数组,返回这个数组对象
        //Function<Integer, int[]> f = n -> new int[n];
        Function<Integer, int[]> f=int[]::new;
        System.out.println(f.apply(4).length);
    }
}
      4.特殊的非静态方法
              /*
                特殊的非静态方法的引用
                    格式:
                     类名::非静态方法名
                  ***1.不再适用于放啊引用的前提条件
                     2.当Lambda表达式第一个参数,作为实例(非静态)方法的调用者,第二个参数作为实例对象的参数,可以受用  类名::非静态方法名
                     3.当Lambda表达式的参数作为一个空参实例方法的调用者时候,也可使用  类名::非静态方法名
              */

import org.junit.Test;

import java.util.function.BiPredicate;
import java.util.function.Function;

/*
  特殊的非静态方法的引用
      格式:
       类名::非静态方法名
       1.不再适用于放啊引用的前提条件
       2.当Lambda表达式第一个参数,作为实例(非静态)方法的调用者,第二个参数作为实例对象的参数,可以受用  类名::非静态方法名
       3.当Lambda表达式的参数作为一个空参实例方法的调用者时候,也可使用  类名::非静态方法名
 */
public class MethodRefDemo05 {
    @Test
    public void test01() {
        Person p1 = new Person("老王");
        Person p2 = new Person("老李");
        //BiPredicate<Person, Person> bp = (person1, person2) -> person1.equals(person2);
        BiPredicate<Person, Person> bp = Person::equals;
        System.out.println(bp.test(p1, p2));
    }

    @Test
    public void test02() {
        Person p1 = new Person("老王");
        //Function<Person, String> f = person -> person.getName();
        Function<Person, String> f = Person::getName;
        System.out.println(f.apply(p1));
    }
}
二.Stream流
    1.Stream流概述
      Strean流的出现是为了增强集合和数组的操作,Stream流更专注于数据的转换,过滤,获取等一系列操作
      同时Stream流提高了操作集合和数组的小笼包,简化了代码
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/*
  Stream流的概述
  统计后缀名为.txt文件名称的个数
 */
public class StreamDemo01 {
    @Test
    public void test01() {
        ArrayList<String> al = new ArrayList<String>();
        al.add("1.txt");
        al.add("2.txt");
        al.add("3.pdf");
        al.add("4.docx");
        int count=0;
        for (String s : al) {
            if (s.endsWith(".txt")) {
                count++;
            }
        }
        System.out.println(count);

    }

    @Test
    public void test02() {
        List<String> list = Arrays.asList("1.txt", "2.txt", "3.pdf", "4.docx");
        /*long count = list.stream().filter(str -> str.endsWith(".txt")).count();
        System.out.println(count);*/
        System.out.println(list.stream().filter(str -> str.endsWith(".txt")).count());
    }
}
    2.Stream流操作步骤
        1.根据数据源获取一个Stream对象
                /*
                  集合或数组流对象的获取
                    集合:
                       Collection体系:都是通过Stream()方法来获取一个流对象





                            List
                            Set
                       Map体系:  需要转换到Collection体系的集合,才能调用stream()方法获取一个流对象
                            HashMap
                       数组:
                            static <T> Stream<T> of(T... values)
                                    返回一个元素为指定值的顺序排列的流。
                */

import org.junit.Test;

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

/*
  集合或数组流对象的获取
    集合:
       Collection体系:都是通过Stream()方法来获取一个流对象
            List
            Set
       Map体系:  需要转换到Collection体系的集合,才能调用stream()方法获取一个流对象
            HashMap
       数组:
           static <T> Stream<T> of(T... values)
                    返回一个元素为指定值的顺序排列的流。
 */
public class StreamDemo02 {
    @Test
    public void test01() {
        Stream<Stream> stream1 = new ArrayList<Stream>().stream();//Stream流上的泛型和集合中元素的类型相对应
                                                                   //当我们通过集合对象来调用stream()方法,相当于
                                                                  //将集合中的元素添加到Stream流中等待操作
        Stream<Integer> stream2 = new HashSet<Integer>().stream();//Stream流上的泛型和集合中元素的类型相对应
    }

    @Test
    public void test02() {
        new HashMap<Integer,Stream>().keySet().stream();//需要将Map转换成Collection体系的集合,就可以使用stream()方法获取流对象
                                                        //将一个个key添加到stream中
        new HashMap<Integer,String>().entrySet().stream();//将一个entry对象{key=value}添加到stream流中
    }

    @Test
    public void test03() {
        int[] arr = {1, 3, 9};
        Stream<int[]> stream1 = Stream.of(arr);//如果通过基本类型数组获取一个流对象,此时六种只有一个元素:这个数组对象

        Integer[] arr2 = {1, 3, 9};
        Stream<Integer> stream2 = Stream.of(arr2);//我们通过基本类型对应的包装类的引用类型数组,获取流对象,此时相当于将数组中的元素添加到流中

        Stream<String> stream3 = Stream.of("abc", "def", "ghk");//通过一串数据获取流对象
        Stream<Integer> stream4 = Stream.of(3, 5, 7);
    }
}
        2.通过Stream对象可以进行0次或多次中间操作
                 /*
                  中间操作:
                      过滤操作
                         filter:传入一个Predicate,根据Predicate中的条件对流中的元素做一个筛选,满足条件保留,不满足的剔除
                      排序操作:
                         sorted:可以根据指定的规则,将流中的元素从小到大排序
                      去重操作
                         distinct:去除流中重复的元素
                      截取操作
                         limit:根据传入的值,来决定截取流总元素的个数
                         skip: 根据传入的值,决定跳过流中的元素个数
                      映射操作
                         map:讲义中数据根据指定操作映射成另一种数据
                            mapToInt
                            mapToDouble
                            mapToLong
                  */

public class Student {
    //学生姓名
    private String name;
    //语文成绩
    private double chineseScore;
    //数学成绩
    private double mathScore;

    public Student(String name, double chineseScore, double mathScore) {
        this.name = name;
        this.chineseScore = chineseScore;
        this.mathScore = mathScore;
    }

    public String getName() {
        return name;
    }

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

    public double getChineseScore() {
        return chineseScore;
    }

    public void setChineseScore(double chineseScore) {
        this.chineseScore = chineseScore;
    }

    public double getMathScore() {
        return mathScore;
    }

    public void setMathScore(double mathScore) {
        this.mathScore = mathScore;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", chineseScore=" + chineseScore +
                ", mathScore=" + mathScore +
                '}';
    }
}
/*
 中间操作:
     过滤操作
        filter:传入一个Predicate,根据Predicate中的条件对流中的元素做一个筛选,满足条件保留,不满足的剔除
     排序操作:
        sorted:可以根据指定的规则,将流中的元素从小到大排序
     去重操作
        distinct:去除流中重复的元素
     截取操作
        limit:根据传入的值,来决定截取流总元素的个数
        skip: 根据传入的值,决定跳过流中的元素个数
     映射操作
        map:讲义中数据根据指定操作映射成另一种数据
           mapToInt
           mapToDouble
           mapToLong



  班级中有5个人姓名,语文成绩,数学成绩分别如下
  李雷, 70, 90
  韩梅梅,  30, 100
  李宁,  85, 80
  王松,70,60
  张家界,90,73

  需求:
      1.打印语文成绩>80的学生信息
      2.打印数学成绩前三名的学生信息
      3.打印数学成绩倒数第一和倒数第二的学生信息
      4.获取全班数学的平均成绩
      5.获取全班语文成绩(不包含重复成绩)
      6.将语文成绩或数学成绩在[80,90]之间的学生的姓名收集到一个集合中
 */

import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

public class StreamDemo04 {
    //@Before会在所有的@Test注解之前执行
    List<Student> students;
    @Before
    public void init() {
        //初始化数据源
         students= Arrays.asList(
                new Student("李雷", 70, 90),
                new Student("韩梅梅", 30, 100),
                new Student("李宁", 85, 80),
                new Student("王松", 70, 60),
                new Student("张家界", 90, 73)
        );

    }

    @Test
    public void test02() {
        //1.打印语文成绩>80的学生信息
        students.stream().filter(stu -> stu.getChineseScore() > 80).forEach(System.out::println);
    }

    @Test
    public void test03() {
        //2.打印数学成绩前三名的学生信息
        /*
           a.首先需要对学生的成绩从大到小排序
           b.获取前三名的信息
         */
        students.stream()
                .sorted((stu1,stu2)->(int)(stu2.getMathScore()-stu1.getMathScore()))
                .limit(3)//截取流中的前三个元素
                .forEach(System.out::println);
    }

    @Test
    public void test04() {
        // 3.打印数学成绩倒数第一和倒数第二的学生信息
        /*
          a.首先需要对学生的数学成绩从大到小排序
          b.获取倒数第一和倒数第二
         */
        students.stream()
                .sorted((stu1, stu2) -> (int) (stu2.getMathScore() - stu1.getMathScore()))
                .skip(students.size() - 2)
                .forEach(System.out::println);
    }

    @Test
    public void test05() {
        //4.获取全班数学的平均成绩
        //将流中的以恶搞个学生对象映射成每个学生对应的数学成绩
        double avgScore = students.stream().mapToDouble(stu -> stu.getMathScore()).average().getAsDouble();
        System.out.println(avgScore);
    }

    @Test
    public void test06() {
        // 5.获取全班语文成绩(不包含重复成绩)
        // 需要使用mapToDouble
        //students.stream().mapToDouble(stu->stu.getChineseScore()).distinct().forEach(System.out::println);
        //students.stream().map(stu->stu.getChineseScore()).distinct().forEach(System.out::println);
        students.stream().map(Student::getChineseScore).distinct().forEach(System.out::println);
    }

    @Test
    public void test07() {
        // 6.将语文成绩或数学成绩在[80,90]之间的学生的姓名收集到一个集合中
        //a.语文成绩在[80,90]之间的学生(Predicate) 或者 数学成绩在[80,90]之间(Predicate)
        //b.将过滤后的一个个学生对象映射成一个个学生姓名
        //c.将过滤和映射中间操作后的数据收集到以恶搞集合中
        Predicate<Student>p1=stu->stu.getChineseScore()>=80&&stu.getChineseScore()<=90;
            Predicate<Student>p2=stu->stu.getMathScore()>=80&&stu.getMathScore()<=90;
        List<String> names = students.stream()
                .filter(p1.or(p2))
                .map(Student::getName)
                .collect(Collectors.toList());

        System.out.println(names);
    }
}
        3.进行一次最终操作获取最终结果
               /*
                 Stream流的最终操作:
                    1.迭代
                      forEach:逐个消费流中的元素
                    2.统计
                      count:统计流中元素的个数
                      max :按照一定比较规则(Comparator接口实现规则),来获取流中最大元素
                      min :按照一定比较规则(Comparator接口实现规则),来获取流中最小元素
                    3.查找
                      findFirst
                    4.匹配
                      allMatch:只有流中所有的元素都满足Predicate(条件),allMatch方法才返回true,否则返回false
                      anyMatch:只有流中有一个元素满足Predicate(条件),anyMatch方法才返回true,否则返回false
                      noneMatch:只有流中所有的元素都不满足Predicate(条件),noneMatch方法才返回true,否则返回false
                    5.收集
                      collect:我们可以将最终操作结果收集到一个集合(List,Set,Map)
                               我们主要通过Collections.toList(),Collections.toSet(),Collections.toMap(),将最终操作结果收集到不同集合中

                 中间操作:
                     sorted
                */

import org.junit.Test;

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

/*
  Stream流的最终操作:
     1.迭代
       forEach:逐个消费流中的元素
     2.统计
       count:统计流中元素的个数
       max :按照一定比较规则(Comparator接口实现规则),来获取流中最大元素
       min :按照一定比较规则(Comparator接口实现规则),来获取流中最小元素
     3.查找
       findFirst
     4.匹配
       allMatch:只有流中所有的元素都满足Predicate(条件),allMatch方法才返回true,否则返回false
       anyMatch:只有流中有一个元素满足Predicate(条件),anyMatch方法才返回true,否则返回false
       noneMatch:只有流中所有的元素都不满足Predicate(条件),noneMatch方法才返回true,否则返回false
     5.收集
       collect:我们可以将最终操作结果收集到一个集合(List,Set,Map)
                我们主要通过Collections.toList(),Collections.toSet(),Collections.toMap(),将最终操作结果收集到不同集合中

   中间操作:
      sorted
 */
public class StreamDemo03 {
    List<String> list = Arrays.asList("zhangsan", "lisi", "laowang");

    @Test
    public void test01() {

        //list.stream().forEach(str-> System.out.println(str));
        list.stream().forEach(System.out::println);
    }

    @Test
    public void test02() {
        long count = list.stream().count();
        System.out.println(count);
    }

    @Test
    public void test03() {
        list.stream().sorted().forEach(System.out::println);//字符串的默认排序方式是字典顺序
        System.out.println("------------");
        /*
          Comparator接口的
               int compare(T o1, T o2);
                  如果compare方法返回一个正数,默认为o1>o2
                  如果compare方法返回一个负数,默认为o1<o2
                  如果compare方法返回0,默认为o1=o2
              sorted方法默认按照元素从小到大排序
              比较流程:
              str1="lisi"
              str2="zhangsan"
              str1.length() - str2.length()<0 => "lisi"<"zhangsan"
              第二种情况:str2.length() - str1.length() >0 =>"lisi">"zhangsan"

              str1="laowang"
              str2="zhangsan"
              str1.lemgth() - str2.length() => "laowang"<"zhangsan"
              第二种情况: str2.length() - str1.length()>0 =>"laowang">"zhangsan"

              str1="laowang"
              str2="lisi"
              str1.length() - str2.length() => "laiwang">"lisi"
              第二种情况: str2.length() - str1.length()<0 => "laowang"<"kisi"

              最终结果: list<laowang<zhangsan
              第二种情况最终结果: zhangsan<laowang<lisi

         */
        list.stream().sorted((str1, str2) -> str1.length() - str2.length()).forEach(System.out::println);
        System.out.println("-------------------");
        list.stream().sorted((str1, str2) -> str2.length() - str1.length()).forEach(System.out::println);
    }

    //List<String> list = Arrays.asList("zhangsan", "lisi", "laowang");
    @Test
    public void test04() {
        //获取最大长度的字符串
        System.out.println(list.stream().max((str1, str2) -> str1.length() - str2.length()).get());

        //获取最小长度字符串
        System.out.println(list.stream().min((str1, str2) -> str1.length() - str2.length()).get());
    }

    @Test
    public void test05() {
        System.out.println(list.stream().findFirst().get());
    }

    @Test
    public void test06() {
        System.out.println(list.stream().allMatch(str -> str.length() > 4));//false
        System.out.println(list.stream().anyMatch(str -> str.length() > 4));//true
        System.out.println(list.stream().noneMatch(str -> str.length() > 4));//true
    }

    @Test
    public void test07() {
        Stream<String> stream = list.stream();
        List<String> l = stream.collect(Collectors.toList());//将流中的数据收集到List集合中
        System.out.println(l.getClass());
        System.out.println(l.size());
    }
    @Test
    public void test08() {
        Set<String> set = list.stream().collect(Collectors.toSet());
        System.out.println(set);
    }

    @Test
    public void test09() {
        //将字符串的长度作为ley,字符串的值作为value去构造一个map
        Map<Integer, String> map = list.stream().collect(Collectors.toMap(str -> str.length(), str -> str));
        System.out.println(map);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值