day22-JDK新特性

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

接口中的新特性

接口我们之前已经学过了那么接口中内部主要就是封装了方法包含抽象方法JDK 7及以前默认方法和静态方法JDK 8私有方法 JDK 9。

接口中可以有的内容

  • JDK1.7之前

    抽象方法

    常量

  • JDK1.8

    默认方法
    静态方法

  • JDK1.9

    私有方法

接口默认方法的定义和使用

默认方法使用 default 修饰不可省略供子类调用或者子类重写。

默认方法定义格式

public default 返回值类型  方法的名称(参数列表){
    方法体
}

默认方法的好处

接口的默认方法实现类可以不用重写默认方法可以用于接口升级

/**
 * @Auther: yanqi
 * @Desc   实现类没有没重写默认方法呢
 *              接口中的抽象方法是必须要重写实现
 *              接口中的默认方法不用重写也可以手动重写,你默认方法存在的意义
 *
 *              如果今后项目代码已以经写好后期可能要扩展接口中加新的方法功能如果你加抽象方法功能
 *              所有的实现类有影响所以针对以上后期可能要扩展功能的话代码的维护性比较差出现了默认方法
 */
  • 定义接口
    public interface LiveAble {
        //接口的默认方法
        public default void fly(){ 
            System.out.println("天上飞"); 
        } 
    }
    
  • 定义实现类
    public class Animal implements LiveAble {    
        // default 可以选择是否重写,也可以根据实际需求进行重写
        /*
        	@Override
       		public void fly() {
            	System.out.println("自由自在的飞");   
            }
        */
    }
    
  • 定义测试类
    public class InterfaceDemo {
        public static void main(String[] args) {       
            // 创建子类对象 
            Animal a = new Animal();
            // 调用默认方法
            a.fly();
        }
    }
    

接口静态方法的定义和使用

静态方法使用 static 修饰供接口直接调用。

静态与.class文件相关只能使用接口名调用不可以通过实现类的类名或者实现类的对象调用

静态方法定义格式

public static 返回值类型 方法名称(参数列表){
    方法体
}

静态方法使用

  • 定义接口
    public interface LiveAble {
        //静态方法
        public static void show2(){
            System.out.println("静态方法-show2");
        }
    }
    
  • 定义实现类
    public class Animal implements LiveAble {    
      // 无法重写静态方法
    }
    
  • 定义测试类
    public class InterfaceDemo {
        public static void main(String[] args) {
            //无法调用
            // LiveAble l = new LiveAbleImpl();
            // l.show2();
            
            //接口名.静态方法(参数列表)
           LiveAble.show2();
        } 
    }
    

接口私有方法的定义和使用

如果一个接口中有多个默认方法并且方法中有重复的内容那么可以抽取出来封装到私有方法中供默认方法 去调用。从设计的角度讲私有的方法是对默认方法和静态方法的辅助。

私有方法分类

  • 普通私有方法

    只有默认方法可以调用。

  • 私有静态方法

    默认方法和静态方法可以调用。

代码演示

  • 私有方法
    • 定义接口

      public interface MyInterfacePrivateA {
      	//默认方法
          public default void methodDefault1() {
              System.out.println("默认方法1");
              methodCommon();
          }
      
          //默认方法
          public default void methodDefault2() {
              System.out.println("默认方法2");
              methodCommon();
          }
      
          //普通-私有方法
          private void methodCommon() {
              System.out.println("AAA");
              System.out.println("BBB");
              System.out.println("CCC");
          }
      
      }
      
  • 私有静态方法

    • 定义接口

      public interface MyInterfacePrivateB {
          //静态方法
          public static void methodStatic1() {
              System.out.println("静态方法1");
              methodStaticCommon();
          }
      
          //静态方法
          public static void methodStatic2() {
              System.out.println("静态方法2");
              methodStaticCommon();
          }
      
          //私有-静态方法
          private static void methodStaticCommon() {
              System.out.println("AAA");
              System.out.println("BBB");
              System.out.println("CCC");
          }
      }
      

    私有方法主要解决的问题是:

默认方法和static方法代码重复的问题,private方法可作为抽取共性

Lambda表达式

什么是Lambda

Lambda 表达式是 Java8 新增的重要特性Lambda 使 Java 具有了类似函数式编程的风格其实 Lambda 表达式也是一个 “语法糖”其实质也是由编译器根据表达式推断最终生成原始语法的字节码方式。

image-20211118115518550

面象对象思想

做一件事情找一个能解决这个事情的对象调用这个对象的方法完成事情

函数式编程思想

只要能获取到结果谁去做的怎么做的都不重要重视的是结果不重视过程

函数式思想

函数式思想则尽量忽略面向对象的复杂语法“强调做什么而不是以什么形式去做”

而我们要学习的Lambda表达式就是函数式思想的体现

函数式接口

函数式接口在java中指的是有且仅有一个抽象方法的接口

当然接口中可以有其他的方法默认方法静态方法私有方法
函数式接口的使用 一般用作方法的参数和返回值类型

体验Lambda

  • 案例需求

    启动一个线程在控制台输出一句话多线程程序启动了

  • 实现步骤

    - 定义一个类MyRunnable实现Runnable接口重写run()方法
    - 创建MyRunnable类的对象
    - 创建Thread类的对象把MyRunnable的对象作为构造参数传递
    - 启动线程
    
  • 代码实现

    • 定义线程类
      public class MyRunnable implements Runnable {
      
          @Override
          public void run() {
              System.out.println("多线程程序启动了");
          }
      }
      
    • new Thread 方式
      //方式一
      MyRunnable my = new MyRunnable();
      Thread t = new Thread(my);
      t.start();
      
    • 匿名内部类方式
      //方式二
      new Thread(new Runnable() {
          @Override
          public void run() {
              System.out.println("多线程程序启动了");
          }
      }).start();
      
    • Lambda实现
      //方式三
      new Thread( () -> {
          System.out.println("多线程程序启动了");
      } ).start();
      

Lambda标准格式

  • 格式

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

  • 格式解析
    • 形式参数如果有多个参数参数之间用逗号隔开如果没有参数留空即可

    • ->由英文中画线和大于符号组成固定写法。代表指向动作

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

Lambda表达式练习

Lambda表达式使用前提

  • 有一个接口
  • 接口中有且仅有一个抽象方法
/**
 * @Auther: yanqi
 * @Desc: 函数式接口在java中指的是有且仅有一个抽象方法的接口
 *        当然接口中可以有其他的方法默认方法静态方法私有方法
          **函数式接口的使用 一般用作方法的参数和返回值类型**
 *
 *          @FunctionalInterface
 *          作用可以检测接口是不是一个函数式接口
 *              是编译成功
 *              否编译失败(接口中没有抽象方法抽象方法多于1个)
 */

@FunctionalInterface
public interface LambdaInter{

    //定义一个抽象方法
    public abstract void method();

    // public abstract  void method2();//编译不通过只能有一个抽象方法

}

抽象方法是无参无返回值

  • 实现步骤
    • 定义一个接口(Eatable)里面定义一个抽象方法void eat();

    • 定义一个测试类(EatableDemo)在测试类中提供两个方法

      • 一个方法是useEatable(Eatable e)

      • 一个方法是主方法在主方法中调用useEatable方法

  • 代码实现
    //接口
    public interface Eatable {
        //抽象方法无参无返回值
        void eat();
    }
    //实现类
    public class EatableImpl implements Eatable {
        @Override
        public void eat() {
            System.out.println("一天一苹果医生远离我");
        }
    }
    
    /** 
     * 测试类
     * @Auther: yanqi
     * @Desc **函数式接口的使用 一般用作方法的参数和返回值类型**
     */
    public class EatableDemo {
        public static void main(String[] args) {
            //方式一匿名内部类
            useEatable(new Eatable() {
                @Override
                public void eat() {
                    System.out.println("方式一匿名内部类");
                }
            });
    
            //方式二Lambda表达式
            //()表示eat()方法的参数列表{}内部表示方法体
            useEatable(()->{
                System.out.println("方式二Lambda表达式");
            });
        }
    
        //定义一个方法参数用我们定义的函数式接口
        private static void useEatable(Eatable e) {
            e.eat();
        }
    
    }
    
    

抽象方法是有参无返回值

  • 实现步骤
    • 定义一个接口(Flyable)里面定义一个抽象方法void fly(String s);

    • 定义一个测试类(FlyableDemo)在测试类中提供两个方法

      • 一个方法是useFlyable(Flyable f)

      • 一个方法是主方法在主方法中调用useFlyable方法

  • 代码实现
    public interface Flyable {
        //抽象方法是有参无返回值
        void fly(String s);
    }
    
    public class FlyableDemo {
        public static void main(String[] args) {
       
            //方式一匿名内部类
            useFlyable(new Flyable() {
                @Override
                public void fly(String s) {
                    System.out.println(s);
                    System.out.println("飞机自驾游");
                }
            });
            System.out.println("--------");
    
            //方式二Lambda表达式
            //useFlyable((String s) -> {
            useFlyable((s) -> { //类型也可以省略lambda表达式会自己行判断类型   
                System.out.println(s);
                System.out.println("飞机自驾游");
            });
    
        }
    
        private static void useFlyable(Flyable f) {
            f.fly("风和日丽晴空万里");
        }
    }
    

抽象方法是有参有返回值

  • 操作步骤
    • 定义一个接口(Addable)里面定义一个抽象方法int add(int x,int y);

    • 定义一个测试类(AddableDemo)在测试类中提供两个方法

      • 一个方法是useAddable(Addable a)

      • 一个方法是主方法在主方法中调用useAddable方法

  • 代码实现
    public interface Addable {
        // 抽象方法是有参有返回值
        int add(int x,int y);
    }
    
    public class AddableDemo {
        public static void main(String[] args) {
            //方式一匿名内部类
            useAddable(new Addable() {
                @Override
                public int add(int x, int y) {
                    return x+y;
                }
            });
            
            //方式二lambda
            useAddable((int x,int y) -> {
                return x + y;
            });
            //可以省略类型
            useAddable((x,y)->{
               return x+y;
            });
            //如果代码块的语句只有一条可以省略大括号和分号和return关键字不建议
            useAddable((x,y)->
                 x+y
            );
    
        }
    
        private static void useAddable(Addable a) {
            int sum = a.add(10, 20);
            System.out.println(sum);
        }
    }
    

Lambda表达式的省略模式

省略规则

  • 参数类型可以省略。但是有多个参数的情况下不能只省略一个
  • 如果参数有且仅有一个那么小括号可以省略
  • 如果代码块的语句只有一条可以省略大括号和分号和return关键字

代码演示

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

public interface Flyable {
    void fly(String s);
}

public class LambdaDemo {
    public static void main(String[] args) {
//        useAddable((int x,int y) -> {
//            return x + y;
//        });
        //参数的类型可以省略
        useAddable((x, y) -> {
            return x + y;
        });

//        useFlyable((String s) -> {
//            System.out.println(s);
//        });
        //如果参数有且仅有一个那么小括号可以省略
//        useFlyable(s -> {
//            System.out.println(s);
//        });

        //如果代码块的语句只有一条可以省略大括号和分号
        useFlyable(s -> System.out.println(s));

        //如果代码块的语句只有一条可以省略大括号和分号如果有returnreturn也要省略掉
        useAddable((x, y) -> x + y);
    }

    private static void useFlyable(Flyable f) {
        f.fly("风和日丽晴空万里");
    }

    private static void useAddable(Addable a) {
        int sum = a.add(10, 20);
        System.out.println(sum);
    }
}

Lambda表达式的注意事项

  • 使用Lambda必须要有接口并且要求接口中有且仅有一个抽象方法

  • 必须有上下文环境才能推导出Lambda对应的接口

    • 根据局部变量的赋值得知Lambda对应的接口

      Runnable r = () -> System.out.println(“Lambda表达式”);

    • 根据调用方法的参数得知Lambda对应的接口

      new Thread(() -> System.out.println(“Lambda表达式”)).start();

lambda表达式主要用于替换以前广泛使用的内部匿名类使代码更简洁

Stream流

它可以指定你希望对集合进行的操作可以执行非常复杂的查找、过滤和映射数据等操作。

Stream流是数据渠道用于操作数据源集合、数组等所生成的元素序列。

体验Stream流

  • 案例需求

    按照下面的要求完成集合的创建和遍历

    • 创建一个集合存储多个字符串元素
    • 把集合中所有以"张"开头的元素存储到一个新的集合
    • 把"张"开头的集合中的长度为3的元素存储到一个新的集合
    • 遍历上一步得到的集合
  • 原始方式示例代码

    public class StreamDemo {
        public static void main(String[] args) {
            //1、创建一个集合存储多个字符串元素
            ArrayList<String> list = new ArrayList<>();
            list.add("林青霞");
            list.add("张曼玉");
            list.add("王祖贤");
            list.add("柳岩");
            list.add("张敏");
            list.add("张无忌");
    
            //2、把集合中所有以"张"开头的元素存储到一个新的集合
            ArrayList<String> zhangList = new ArrayList<>();
            for(String s : list) {
                if(s.startsWith("张")) {
                    zhangList.add(s);
                }
            }
            System.out.println(zhangList);//[张曼玉, 张无忌]
    
            //3、把"张"开头的集合中的长度为3的元素存储到一个新的集合
            ArrayList<String> threeList = new ArrayList<>();
            for(String s : zhangList) {
                if(s.length() == 3) {
                    threeList.add(s);
                }
            }
            System.out.println(threeList);//张曼玉 张无忌
    
            //4、遍历上一步得到的集合
            for(String s : threeList) {
                System.out.println(s);
            }
        }
    }
    
  • 使用Stream流示例代码
    public class StreamDemo {
        public static void main(String[] args) {
            //创建一个集合存储多个字符串元素
            ArrayList<String> list = new ArrayList<String>();
    
            list.add("林青霞");
            list.add("张曼玉");
            list.add("王祖贤");
            list.add("柳岩");
            list.add("张敏");
            list.add("张无忌");
    
            //Stream流来改进  s表示的list集合的String类型
            list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println);
            
            System.out.println("========遍历集合========");
            list.forEach(System.out::println);
            
            System.out.println("========遍历数组========");
            //定义数组
             String[] s = {"hello","world","java","yiyan"};
            //数组需要先转成流才能使用
            Arrays.stream(s).forEach(System.out::println);
        }
    }
    

Stream流的好处

  • 直接阅读代码的字面意思即可完美展示无关逻辑方式的语义获取流、过滤姓张、过滤长度为3、逐一打印

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

Stream流的思想

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QT2L6TDj-1673935761393)(assets/image-20210512182253047.png)]

获取Stream流的三种方式

  • Collection体系集合

    使用默认方法stream()生成流 default Stream stream()

  • Map体系集合

    把Map转成Set集合间接的生成流

  • 数组

    通过Stream接口的静态方法of(T… values)生成流

3.3.2 代码演示

public class StreamDemo {
    public static void main(String[] args) {
        //Collection体系的集合可以使用默认方法stream()生成流
        List<String> list = new ArrayList<String>();
        Stream<String> listStream = list.stream();

        Set<String> set = new HashSet<String>();
        Stream<String> setStream = set.stream();

        //Map体系的集合间接的生成流
        Map<String,Integer> map = new HashMap<String, Integer>();
        Stream<String> keyStream = map.keySet().stream();
        Stream<Integer> valueStream = map.values().stream();
        Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();

        //数组可以通过Stream接口的静态方法of(T... values)生成流
        String[] strArray = {"hello","world","java"};
        Arrays.stream(strArray).forEach(System.out::println);
        Stream<String> strArrayStream = Stream.of(strArray);
        Stream<String> strArrayStream2 = Stream.of("hello", "world", "java");
        Stream<Integer> intStream = Stream.of(10, 20, 30);
    }
}

Stream流中间操作方法

概念

中间操作的意思是执行完此方法之后Stream流依然可以继续执行其他操作。

  • 一个中间操作链对数据源的数据进行处理。
  • 多个中间操作可以连接起来形成一个流水线

3.4.2 常见方法

方法名说明
Stream filter(Predicate predicate)用于对流中的数据进行过滤
Stream limit(long maxSize)返回此流中的元素组成的流截取前指定参数个数的数据
Stream skip(long n)跳过指定参数个数的数据返回由该流的剩余元素组成的流
static Stream concat(Stream a, Stream b)合并a和b两个流为一个流
Stream distinct()返回由该流的不同元素根据Object.equals(Object) 组成的流
Stream sorted()返回由此流的元素组成的流根据自然顺序排序
Stream map(Function mapper)返回由给定函数应用于此流的元素的结果组成的流
IntStream mapToInt(ToIntFunction mapper)返回一个IntStream其中包含将给定函数应用于此流的元素的结果

filter方法

用于对流中的数据进行过滤

public class StreamDemo01 {
    public static void main(String[] args) {
        //创建一个集合存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");
        list.add("张敏");
        list.add("张无忌");

        //需求1把list集合中以张开头的元素在控制台输出
        list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);
        System.out.println("--------");

        //需求2把list集合中长度为3的元素在控制台输出
        list.stream().filter(s -> s.length() == 3).forEach(System.out::println);
        System.out.println("--------");

        //需求3把list集合中以张开头的长度为3的元素在控制台输出
        list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println);
                      
        //简化for循环
        list.forEach(System.out::println);
    }
}

limit&skip

返回此流中的元素组成的流截取前指定参数个数和跳过指定个数的数据

public class StreamDemo02 {
    public static void main(String[] args) {
        //创建一个集合存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");
        list.add("张敏");
        list.add("张无忌");

        //需求1取前3个数据在控制台输出
        list.stream().limit(3).forEach(System.out::println);
        System.out.println("--------");

        //需求2跳过3个元素把剩下的元素在控制台输出
        list.stream().skip(3).forEach(System.out::println);
        System.out.println("--------");

        //需求3跳过2个元素把剩下的元素中前2个在控制台输出
        list.stream().skip(2).limit(2).forEach(System.out::println);

    }
}

concat&distinct

concat将两个流合并成为一个流

distinct由该流的不同元素根据Object.equals(Object) 组成的流

public class StreamDemo03 {
    public static void main(String[] args) {
        //创建一个集合存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");
        list.add("张敏");
        list.add("张无忌");

        //需求1取前4个数据组成一个流
        Stream<String> s1 = list.stream().limit(4);
        s1.forEach(System.out::println);

        //需求2跳过2个数据组成一个流
        Stream<String> s2 = list.stream().skip(2);
        s2.forEach(System.out::println);

        //需求3合并需求1和需求2得到的流并把结果在控制台输出
	   //Stream.concat(s1,s2).forEach(System.out::println);

        //需求4合并需求1和需求2得到的流并把结果在控制台输出要求字符串元素不能重复
        Stream.concat(s1,s2).distinct().forEach(System.out::println);
    }
}

sorted

由此流的元素组成的流根据自然顺序排序

public class StreamDemo04 {
    public static void main(String[] args) {
        //创建一个集合存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("linqingxia");
        list.add("zhangmanyu");
        list.add("wangzuxian");
        list.add("liuyan");
        list.add("zhangmin");
        list.add("zhangwuji");

        //需求1按照字母顺序把数据在控制台输出
		list.stream().sorted().forEach(System.out::println);
    }
}

map&mapToInt

map() 返回由给定函数应用于此流的元素的结果组成的流将流中的元素映射到另一个流中

mapToInt 计算流中的数据并返回结果

public class StreamDemo05 {
    public static void main(String[] args) {
        //创建一个集合存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("10");
        list.add("20");
        list.add("30");
        list.add("40");
        list.add("50");

        //需求将集合中的字符串数据转换为整数之后在控制台输出
       list.stream().map(s -> Integer.parseInt(s)).forEach(System.out::println);
       list.stream().map(Integer::parseInt).forEach(System.out::println);

        //int sum() 返回此流中元素的总和
        int result = list.stream().mapToInt(Integer::parseInt).sum();
        System.out.println(result);
    }
}

Stream流终结操作方法

概念

终结操作的意思是执行完此方法之后Stream流将不能再执行其他操作。
一个终止操作执行中间操作链并产生结果。
这是Stream操作中的最后一步终止操作,终止操作会从流的流水线生成结果
例如List、Integer甚至是 void 。

相关方法

方法名说明
void forEach(Consumer action)对此流的每个元素执行操作
long count()返回此流中的元素数

代码演示

public class StreamDemo {
    public static void main(String[] args) {
        //创建一个集合存储多个字符串元素
        ArrayList<String> list = new ArrayList<String>();

        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");
        list.add("张敏");
        list.add("张无忌");

        //需求1把集合中的元素在控制台输出,直接输出结果就不能返回stream对象了
//        list.stream().forEach(System.out::println);

        //需求2统计集合中有几个以张开头的元素并把统计结果在控制台输出
        long count = list.stream().filter(s -> s.startsWith("张")).count();
        System.out.println(count);
    }
}

Stream流综合练习

案例需求

现在有两个ArrayList集合分别存储6名男演员名称和6名女演员名称要求完成如下的操作

  • 男演员只要名字为3个字的前三人

  • 女演员只要姓林的并且不要第一个

  • 把过滤后的男演员姓名和女演员姓名合并到一起

  • 把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据

演员类Actor已经提供里面有一个成员变量一个带参构造方法以及成员变量对应的get/set方法

Actor类

public class Actor {
    private String name;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Actor{" +
                "name='" + name + '\'' +
                '}';
    }
}

案例代码

public class StreamTest {
    public static void main(String[] args) {
        //创建集合
        ArrayList<String> manList = new ArrayList<String>();
        manList.add("周润发");
        manList.add("成龙");
        manList.add("刘德华");
        manList.add("吴京");
        manList.add("周星驰");
        manList.add("李连杰");


        ArrayList<String> womanList = new ArrayList<String>();
        womanList.add("林心如");
        womanList.add("张曼玉");
        womanList.add("林青霞");
        womanList.add("柳岩");
        womanList.add("林志玲");
        womanList.add("王祖贤");

        //男演员只要名字为3个字的前三人
        Stream<String> manStream = manList.stream().filter(s -> s.length() == 3).limit(3);

        //女演员只要姓林的并且不要第一个
        Stream<String> womanStream = womanList.stream().filter(s -> s.startsWith("林")).skip(1);

        //把过滤后的男演员姓名和女演员姓名合并到一起
        Stream<String> stream = Stream.concat(manStream, womanStream);

        //使用map映射到一个新的对象中
        stream.map(s -> new Actor(s)).forEach(System.out::println);
        stream.map(Actor :: new).forEach(System.out::println);
        stream.map(Actor :: new).forEach(a -> System.out.println(a.getName()));

		//
        Stream.concat(manList.stream().filter(s -> s.length() == 3).limit(3),
                womanList.stream().filter(s -> s.startsWith("林")).skip(1)).map(Actor::new).
                forEach(p -> System.out.println(p.getName()));
    }
}

Stream流的收集操作

概念

对数据使用Stream流的方式操作完毕后可以把流中的数据收集到集合中。

常用方法

方法名说明
R collect(Collector collector)把结果收集到集合中
  • 工具类Collectors提供了具体的收集方式
方法名说明
public static Collectors toList()把元素收集到List集合中
public static Collectors toSet()把元素收集到Set集合中
public static Collectors toMap(Function keyMapper,Function valueMapper)把元素收集到Map集合中

代码演示

public class CollectDemo {
    public static void main(String[] args) {
        //创建List集合对象
        List<String> list = new ArrayList<String>();
        list.add("林青霞");
        list.add("张曼玉");
        list.add("王祖贤");
        list.add("柳岩");

        /*
        //需求1得到名字为3个字的流
        Stream<String> listStream = list.stream().filter(s -> s.length() == 3);

        //需求2把使用Stream流操作完毕的数据收集到List集合中并遍历
        List<String> names = listStream.collect(Collectors.toList());
	    names.stream().forEach(System.out::println);
        */

        //创建Set集合对象
        Set<Integer> set = new HashSet<Integer>();
        set.add(10);
        set.add(20);
        set.add(30);
        set.add(33);
        set.add(35);

        /*
        //需求3得到年龄大于25的流
        Stream<Integer> setStream = set.stream().filter(age -> age > 25);

        //需求4把使用Stream流操作完毕的数据收集到Set集合中并遍历
        Set<Integer> ages = setStream.collect(Collectors.toSet());
        ages.stream().forEach(System.out::println);
        */
        //定义一个字符串数组每一个字符串数据由姓名数据和年龄数据组合而成
        String[] strArray = {"林青霞,30", "张曼玉,35", "王祖贤,33", "柳岩,25"};

        //需求5得到字符串中年龄数据大于28的流
        Stream<String> arrayStream = Stream.of(strArray).filter(s -> Integer.parseInt(s.split(",")[1]) > 28);

        //需求6把使用Stream流操作完毕的数据收集到Map集合中并遍历字符串中的姓名作键年龄作值
        //toMap(林青霞,30)
        Map<String, Integer> map = arrayStream.collect(Collectors.toMap(s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1])));

        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            Integer value = map.get(key);
            System.out.println(key + "," + value);
        } 
       //要把map间接转成collection体系下的集合可以使用stream流
        map.keySet().stream().forEach(System.out::println);
        map.values().stream().forEach(System.out::println);
        System.out.println("-----------------");
        map.keySet().stream().forEach(s -> System.out.println(s+":"+map.get(s )));
    }
}

流操作完毕的数据收集到Set集合中并遍历
Set ages = setStream.collect(Collectors.toSet());
ages.stream().forEach(System.out::println);
*/
//定义一个字符串数组每一个字符串数据由姓名数据和年龄数据组合而成
String[] strArray = {“林青霞,30”, “张曼玉,35”, “王祖贤,33”, “柳岩,25”};

    //需求5得到字符串中年龄数据大于28的流
    Stream<String> arrayStream = Stream.of(strArray).filter(s -> Integer.parseInt(s.split(",")[1]) > 28);

    //需求6把使用Stream流操作完毕的数据收集到Map集合中并遍历字符串中的姓名作键年龄作值
    //toMap(林青霞,30)
    Map<String, Integer> map = arrayStream.collect(Collectors.toMap(s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1])));

    Set<String> keySet = map.keySet();
    for (String key : keySet) {
        Integer value = map.get(key);
        System.out.println(key + "," + value);
    } 
   //要把map间接转成collection体系下的集合可以使用stream流
    map.keySet().stream().forEach(System.out::println);
    map.values().stream().forEach(System.out::println);
    System.out.println("-----------------");
    map.keySet().stream().forEach(s -> System.out.println(s+":"+map.get(s )));
}

}


阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6