• Java进阶


    1.Stream流

      关注的是做什么,而不是怎么做

      步骤:(1)拼接流式模型:建立生产线

    用Stream流进行遍历打印

    public class ForStream {
        public static void main(String[] args) {
            List<String> list = new ArrayList<>();
            list.add("林子东");
            list.add("蔡晓武");
            list.add("夏琨");
            list.add("林子成");
            list.add("林峰");
            //对集合进行过滤,要以林开头,且长度为3,最后输出打印
            //首先将集合转换为Stream流
            list.stream()
                    //filter参数是predicate接口,可以用lanmda表达式进行判断
                    .filter(name -> name.startsWith("林"))
                    .filter(name -> name.length()==3)
                    //forEach参数是consumer接口,可以消费打印
                    .forEach(name-> System.out.println(name));
        }
    }

    模型:

    filter 、 map 、 skip 都是在对函数模型进行操作,集合元素并没有真正被处理。只有当终结方法 count执行的时候,整个模型才会按照指定策略执行操作。而这得益于Lambda的延迟执行特性。

    备注:“Stream流”其实是一个集合元素的函数模型,它并不是集合,也不是数据结构,其本身并不存储任何元素(或其地址值)。

    Stream(流)是一个来自数据源的元素队列

      元素是特定类型(指定泛型)的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。

      数据源:流的来源。 可以是集合,数组 等。

    和以前的Collection操作不同, Stream操作还有两个基础的特征:

    • Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluentstyle)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。

    • 内部迭代: 以前对集合遍历都是通过Iterator或者增强for的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式,流可以直接调用遍历方法。

    当使用一个流的时候,通常包括三个基本步骤:获取一个数据源(source)→ 数据转换→执行操作获取想要的结果,每次转换原有 Stream 对象不改变,返回一个新的 Stream 对象(可以有多次转换),这就允许对其操作可以像链条一样排列,变成一个管道。

    2.获取流

    获取一个流非常简单,有以下几种常用的方式:

      所有的 Collection 集合(map集合不行)都可以通过 stream 默认方法获取流;

      Stream 接口的静态方法 of 可以获取数组对应的流。

    public class GetStream {
        public static void main(String[] args) {
            //list集合
            List<String> list = new ArrayList<>();
            Stream<String> stream1 = list.stream();
    
            //set集合
            Set<String> set = new HashSet<>();
            Stream<String> stream2 = set.stream();
    
            //map集合间接调用
            Map<String,String> map = new HashMap<>();
    
            //获取键,存储到一个set集合中
            Set<String> keySet = map.keySet();
            Stream<String> stream3 = keySet.stream();
    
            //获取值,存储到Collection集合中
            Collection<String> values = map.values();
            Stream<String> stream4 = values.stream();
    
            //获取键值对(键与值的映射关系)
            Set<Map.Entry<String, String>> entries = map.entrySet();
            Stream<Map.Entry<String, String>> stream5 = entries.stream();
    
            //把数组转换为stream流
            Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
            //可变参数可以传递数组
            Integer[] arr = {1,2,3,4,5};
            Stream<Integer> stream6 = Stream.of(arr);
        }
    }

     3.Stream流常用方法

      (1)forEach,参数为Consumer接口,用于遍历,属于终结型方法

      (2)filter,参数为Predicate接口,用于过滤,属于延迟方法,返回一个新的流对象

    public class NormalMethod {
        public static void main(String[] args) {
            Stream<String> stream = Stream.of("张三丰", "张志杰", "赵敏");
            //进行过滤
            Stream<String> nameList = stream.filter(name -> name.startsWith("张"));
            //遍历输出
            nameList.forEach(name-> System.out.println(name));
        }
    }

      (3)map,参数为Function接口,用于映射,属于延迟方法,返回一个新的流对象

    public class NormalMethod {
        public static void main(String[] args) {
            Stream<String> stream = Stream.of("1", "2", "3");
            //进行转换
            Stream<Integer> integerStream = stream.map(num -> Integer.parseInt(num));
            //遍历输出
            integerStream.forEach(name-> System.out.println(name));
        }
    }

       (4)count,终结方法,用于统计元素个数,返回一个long类型的数

      (5)limit,延迟方法,用于截取前几个元素,输入几就截取几个,返回一个新的流对象

      (6)skip,跳过前几个,保留后几个,如果有三个元素,输入4,则返回空的流

      (7)Stream的静态方法concat,用于合并两个流,得到一个新的流

    4.方法引用

    方法引用符

      双冒号 :: 为引用运算符,而它所在的表达式被称为方法引用。如果Lambda要表达的函数方案已经存在于某个方法的实现中,那么则可以通过双冒号来引用该方法作为Lambda的替代者。

    语义分析

    例如上例中, System.out 对象中有一个重载的 println(String) 方法恰好就是我们所需要的。那么对于printString 方法的函数式接口参数,对比下面两种写法,完全等效:

      Lambda表达式写法: s -> System.out.println(s);

      方法引用写法: System.out::println

        第一种语义是指:拿到参数之后经Lambda之手,继而传递给 System.out.println 方法去处理。

        第二种等效写法的语义是指:直接让 System.out 中的 println 方法来取代Lambda。两种写法的执行效果完全一样,而第二种方法引用的写法复用了已有方案,更加简洁。

    注:Lambda 中 传递的参数 一定是方法引用中 的那个方法可以接收的类型,否则会抛出异常

    接口:
    @FunctionalInterface
    public interface printable {
        void print(String s);
    }
    打印类:
    public class UpperMethod {
        public void toUp(String s){
            System.out.println(s.toUpperCase());
        }
    }
    主方法:
    public class DemoPrintable {
        public static void main(String[] args) {
            // 先创建对象,通过对象对已存在的方法进行方法引用
            UpperMethod obj = new UpperMethod();
            method(obj::toUp, "ddd");
        }
    
        public static void method(printable p, String s) {
            p.print(s);
        }
    }

     (2)通过类名称引用静态方法

    由于在 java.lang.Math 类中已经存在了静态方法 abs ,所以我们可以直接用类名进行方法引用

    (3)通过super引用父类的成员方法 要求:有子父类 且父类方法存在

    method(super::greet)

    (4)也可以通过this来引用本类的方法 this::method

    (5)类的构造器引用

    接口:
    public interface PersonBuilder {
        //给个名字创建一个Person对象
        Person build(String name);
    }
    Person类:
    public class Person {
        private String name;
    
        public Person() {
        }
    
        public Person(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }
    测试类:
    public class DemoBuildPerson {
        public static void main(String[] args) {
            //类的构造器引用
            /*printName("迪丽热巴",(String name)->{
                return new Person(name);
            });*/
    
            //优化
            printName("迪丽热巴",Person::new);
        }
        public static void printName(String name,PersonBuilder pb){
            Person p1 = pb.build(name);
            System.out.println(p1.getName());
        }
    }
    View Code

     (6)数组的构造器引用

    method(10,int[]::new);
  • 相关阅读:
    inotifywait实时监控文件目录
    centos7支持xming
    ssh目录权限说明
    利用xinetd实现简单web服务器
    python3 使用http.server秒速搭建web服务器
    linux FFMPEG 摄像头采集数据推流
    Linux nginx+rtmp服务器配置实现直播点播
    Nginx中加入nginx-rtmp-module
    ubuntu查看屏幕分辨率
    运用设计原则编写可测试性的代码
  • 原文地址:https://www.cnblogs.com/caixiaowu/p/12915464.html
Copyright © 2020-2023  润新知