精华内容
下载资源
问答
  • JDK 8 Stream

    2019-11-02 22:28:05
    Stream目录Stream的构造与转换包装类型StreamStream转换为其它数据结构map(映射转换)filter(过滤)foreach(for循环)reduce(规则计算)limit(截取前n个元素)skip(丢弃取前n个元素)...JDK 8中的Stream是...

    JDK 8中的Stream是对集合对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作。在JDK 8中使用Stream,代码更加简洁易读;而且使用并发模式,程序执行速度更快。

    Stream的构造与转换

    // 1. Arrays -> Stream
    Stream stream = Stream.of("a", "b", "c");
    
    // 2. Arrays -> Stream
    String [] strArray = new String[] {"a", "b", "c"};
    Stream stream = Stream.of(strArray);
    // 或者 Stream stream = Arrays.stream(strArray);
    
    // 3. Arrays -> Collections -> Stream
    List<String> list = Arrays.asList(strArray);
    Stream stream = list.stream();
    
    // 4. Collections -> Stream
    List<String> list = new ArrayList();
    list.add("1");
    list.add("2");
    list.add("3");
    Stream stream = list.stream();
    

    包装类型Stream

    对于基本数值型,目前有三种对应的包装类型Stream:IntStream、LongStream、DoubleStream。当然我们也可以用 Stream、Stream、Stream,但是 boxing 和 unboxing 会很耗时,所以特别为这三种基本数值型提供了对应的 Stream

    Stream转换为其它数据结构

    // 1. Array
    String[] strArray1 = stream.toArray(String[]::new);
    
    // 2. Collection
    List<String> list1 = stream.collect(Collectors.toList()); // list
    List<String> list2 = stream.collect(Collectors.toCollection(ArrayList::new)); // 指定ArrayList
    Set set1 = stream.collect(Collectors.toSet()); // set
    Stack stack1 = stream.collect(Collectors.toCollection(Stack::new)); // Stack
    
    // 3. Map
    Map<String, Test> testMap1 = stream.collect(Collectors.toMap(Test::getId, test -> test)); // Map<String, Test>
    Map<String, String> testMap2 = stream.collect(Collectors.toMap(Test::getId, Test::getName)); // Map<String, String>
    
    // 4. String
    String str = stream.collect(Collectors.joining()).toString();
    

    map(映射转换)

    • 字符串装换成大写的字符
    List<String> output = wordList.stream().map(String::toUpperCase).collect(Collectors.toList());
    
    • 求平方
    List<Integer> nums = Arrays.asList(1, 2, 3, 4);
    List<Integer> squareNums = nums.stream().map(n -> n * n).collect(Collectors.toList());
    

    filter(过滤)

    在filter中边写过滤的条件

    List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6));
    Integer[] evens = list.stream().filter(n -> n > 3).toArray(Integer[]::new);
    

    foreach(for循环)

    List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6));
    list.stream().filter(n -> n > 3).forEach(p -> System.out.println(p));
    

    reduce(规则计算)

    根据一定的规则将Stream中的元素进行计算后返回一个唯一的值

    • 求和
    int sum1 = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum); // 无起始值
    int sum2 = Stream.of(1, 2, 3, 4).reduce(10, Integer::sum); // 有起始值
    
    • 字符串拼接
    String concat = Stream.of("a", "b", "c", "d").reduce("", String::concat);
    
    • 最大值
    int max = Stream.of(10, 30, 40, 5).reduce(Integer.MIN_VALUE, Integer::max);
    
    • 最小值
    double min = Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min);
    

    limit(截取前n个元素)

    List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6));
    List<Integer> collect = list.stream().limit(5).collect(Collectors.toList());
    

    skip(丢弃取前n个元素)

    List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6));
    List<Integer> collect = list.stream().skip(3).collect(Collectors.toList());
    

    sorted(排序)

    /**
     * 从小到大排序
     */
    @Data
    @AllArgsConstructor
    static class Person implements Comparable {
        public int id;
        private String name;
    
        @Override
        public int compareTo(Object o) {
            return 0;
        }
    }
    
    public static void main(String[] args) {
        List<Person> persons = new ArrayList<>();
        for (int i = 1; i <= 5; i++) {
            Person person = new Person(i, "name" + i);
            if (i == 2) {
                person.setId(10);
            }
            persons.add(person);
        }
        persons.stream().forEach(p -> System.out.println(p));
        persons.stream().sorted(Comparator.comparing(Person::getId)).forEach(p -> System.out.println(p));
    }
    
    /**
     * 从大到小排序
     */
    @Data
    @AllArgsConstructor
    static class Person implements Comparable {
        public int id;
        private String name;
    
        @Override
        public int compareTo(Object o) {
            return 0;
        }
    }
    
    public static void main(String[] args) {
        List<Person> persons = new ArrayList<>();
        for (int i = 1; i <= 5; i++) {
            Person person = new Person(i, "name" + i);
            if (i == 2) {
                person.setId(10);
            }
            persons.add(person);
        }
        persons.stream().forEach(p -> System.out.println(p));
        persons.stream().sorted(Comparator.comparing(Person::getId).reversed()).forEach(p -> System.out.println(p));
    }
    

    max/min(最大值/最小值)

    List<Student> students = new ArrayList<>(3);
    students.add(new Student("路飞", 22, 175));
    students.add(new Student("红发", 40, 180));
    students.add(new Student("白胡子", 50, 185));
    
    Optional<Student> max = students.stream()
            .max(Comparator.comparing(stu -> stu.getAge()));
    Optional<Student> min = students.stream()
            .min(Comparator.comparing(stu -> stu.getAge()));
    //判断是否有值
    if (max.isPresent()) {
        System.out.println(max.get());
    }
    if (min.isPresent()) {
        System.out.println(min.get());
    }
    

    count(计数)

    一般都是结合filter使用,因为先筛选出我们需要的再统计即可。及早求值

    List<Student> students = new ArrayList<>(3);
    students.add(new Student("张三", 22, 175));
    students.add(new Student("李四", 40, 180));
    students.add(new Student("王五", 50, 185));
    
    long count = students.stream().filter(student -> student.getAge() < 30).count();
    

    groupingBy(分组)

    根据年龄分组

    List<Student> students = new ArrayList<>(4);
    students.add(new Student("张三", 22, 175));
    students.add(new Student("李四", 22, 170));
    students.add(new Student("王五", 40, 180));
    students.add(new Student("赵六", 50, 185));
    
    Map<Integer, List<Student>> listMap = students.stream().collect(
        Collectors.groupingBy(student -> student.getAge()));
    

    partitioningBy(划分)

    根据年龄是否<30岁来划分

    List<Student> students = new ArrayList<>(4);
    students.add(new Student("张三", 22, 175));
    students.add(new Student("李四", 22, 170));
    students.add(new Student("王五", 40, 180));
    students.add(new Student("赵六", 50, 185));
    
    Map<Boolean, List<Student>> collect = students.stream().collect(
            Collectors.partitioningBy(student -> student.getAge() < 30));
    
    展开全文
  • 文章目录jdk8新特性五: jdk8Stream流操作jdk8之流Streamstream中的函数jdk8里面的并行流parallelStreamjdk8里面的聚合操作reducejdk8的forEach集合jdk8收集器和集合统计jdk8新内存空间Metaspacejdk7里面的新特性try...

    jdk8新特性五: jdk8Stream流操作

    jdk8之流Stream

    1. Stream,中文称为流,通过将集合转换为这么一种叫做流的元素队列,通过声明性方式,能够对集合中的每个元素进行一系列并行和串行的流水线操作。
    2. 元素是特定类型的对象,所以元素集合看作一种流,流在管道中传输,且可以在管道的节点上进行处理。比如排序,聚合,过滤等操作。

    stream流的执行顺序

    1. 操作详情:

    1、数据元素便是原始集合,如list,set,map集合。

    2、生成流,可以是串行流,stream()或者是并行流parallelStream()

    3、中间操作:可以是排序,聚合,过滤,转换。

    4、终端操作:很多流操作本身就会返回一个流,所以多个操作可以直接连接起来,最后统一进行收集。

    1. 例子

    stream().map()是将一个元素映射成另一个元素。stream是生成流,map是中间操作。

    collect()是终端操作。

    List<String> list=Arrays.asList("spring","abc","bcd","amd","efo");
    List<String> resultList = list.stream().map(obj -> "在小d课堂学习" + obj).collect(Collectors.toList());
    System.out.println(resultList);
    

    stream中的函数

    1. map函数

    1、将流中每个元素T映射为R(类似类型转换)

    2、使用场景:在javaweb中将do对象转成dto对象。

    public static void main(String[] args) throws IOException, InterruptedException {
    
    
        List<User> list=Arrays.asList(new User(1,"小的","123"),new User(21,"小c","1234"),new User(31,"小d","1233"),
                                      new User(4,"小的m","1d23"),new User(21,"小d的","12d3"));
        List<UserDto> resultDto = list.stream().map(obj -> {
            UserDto userDto = new UserDto();
            userDto.setUserId(obj.getId());
            userDto.setUsername(obj.getName());
            return userDto;
        }).collect(Collectors.toList());
    
        System.out.println(resultDto);
    
    
    }
    
    1. filter函数

    1、用于通过设置的条件过滤出元素

    2、例如:过滤出字符串长度大于5的字符串

    List<String> list2 = Arrays.asList("springboot", "springcloud",
                                       "redis", "git", "netty", "java", "html", "docker");
    List<String> resultList = list2.stream().filter(obj -> obj.length() >
                                                    5).collect(Collectors.toList());
    System.out.println(resultList);
    
    1. limit函数和sorted函数
    List<String> resultList = list2.stream().sorted().collect(Collectors.toList());
    List<String> resultList = list2.stream().sorted(Comparator.comparing(obj->obj.length())).collect(Collectors.toList());
    List<String> resultList = list2.stream().sorted(Comparator.comparing(obj->obj.length(),Comparator.reverseOrder())).collect(Collectors.toList());
    List<String> resultList = list2.stream().sorted(Comparator.comparing(String::length).reversed()).collect(Collectors.toList());
    List<String> resultList = list2.stream().sorted(Comparator.comparing(String::length)).limit(3).collect(Collectors.toList());
    System.out.println(resultList);
    
    1. allMatch函数

    检查是否匹配所有元素,只有全部符合才返回true

    List<String> list = Arrays.asList("springboot", "springcloud", "redis",
                                      "git", "netty", "java", "html", "docker");
    boolean flag = list.stream().allMatch(obj->obj.length()>1);
    System.out.println(flag);
    
    1. anyMatch函数

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

    List<String> list = Arrays.asList("springboot", "springcloud", "redis",
                                      "git", "netty", "java", "html", "docker");
    boolean flag = list.stream().anyMatch(obj->obj.length()>18);
    System.out.println(flag);
    
    1. Max函数和Min函数,比较出最大值和最小值。

    Optional是新增的类型,可以进行判空操作。

    if(xxx.isPresent()){}

    public static void main(String[] args) throws IOException, InterruptedException {
    
    
    
        List<Student> list = Arrays.asList(new Student(32),new
                                           Student(33),new Student(21),new Student(29),new Student(18));
        //list.stream().max(Comparator.comparingInt(Student::getAge));
        //最⼤
        Optional<Student> optional2 = list.stream().max((s1, s2)->
                                                        Integer.compare(s1.getAge(),s2.getAge()));
        //最⼩
        Optional<Student> optional = list.stream().min((s1, s2)->
                                                       Integer.compare(s1.getAge(),s2.getAge()));
        System.out.println(optional2.get().getAge());
        System.out.println(optional.get().getAge());
    
    }
    

    jdk8里面的并行流parallelStream

    1. 集合做重复操作,如果使用串行执行,会相当耗时,因此一般会采用多线程加快,java8的paralleStream用forkjoin框架提供并发执行能力。
    2. 底层原理

    线程池ForkjoinPool维护一个线程队列

    可以分割任务,将父任务拆分成子任务,完全贴合分治思想。

    1. 问题:

    并行流,不一定比串行流块,当数据量小的时候,并行流还没把任务分出去,说不一定串行流已经执行完了。

    可能会出现线程安全问题。

    1. 线程安全问题例子

    ArrayList()是不安全的,会报异常。

    CopyOnwriteArrayList():是安全的。上了锁。

    for(int i=0;i<10;i++) {
        List list2 = new ArrayList();
        //List list = new CopyOnWriteArrayList();
        IntStream.range(0, 100).parallel().forEach(list2::add);
        System.out.println(list2.size());
    }
    

    jdk8里面的聚合操作reduce

    1. reduce,聚合,就是根据一定的规则将Stream中的元素进行计算后返回一个唯一的值。
    int value = Stream.of(1, 2, 3, 4, 5).reduce((item1, item2) -> item1
                                                + item2).get();
    
    1. 如果不用lambda,就要使用匿名函数。
    int result = Stream.of(1,2,3,4,5).reduce(new
                                             BinaryOperator<Integer>() {
                                                 @Override
                                                 public Integer apply(Integer item1, Integer item2) {
                                                     return item1 + item2;
                                                 }
                                             }).get();
    
    1. 可以设置一个初始值
    int value = Stream.of(1, 2, 3, 4,5).reduce(100, (sum, item) -> sum +
                                               item);
    
    1. 利用聚合reduce求最大值
    int value = Stream.of(1645, 234345, 32,
    44434,564534,435,34343542,212).reduce( (item1, item2) -> item1 >
    item2 ? item1 : item2 ).get();
    System.out.println(value);
    

    jdk8的forEach集合

    1. forEach就是遍历每一个元素,在forEach里面进行对每一个元素进行操作。map也有这种功能。
    2. 注意点:

    1、不能修改包含外部的变量的值。

    2、不能用break或者return或者continue等关键字结束或者循环。

    jdk8收集器和集合统计

    1. Collectors.collect()方法 的使用

    一个终端操作,用于对流中的数据进行归集操作,collect方法接收的参数是一个Collector

    //源代码
    public static <T> Collector<T, ?, List<T>> toList() {
    return new CollectorImpl<>((Supplier<List<T>>)
    ArrayList::new, List::add,(left, right) -> {
    left.addAll(right); return left; }, CH_ID);
    }
    

    ArrayList::new,创建⼀个ArrayList作为累加器

    List::add,对流中元素的操作就是直接添加到累加器中

    reduce操作, 对⼦任务归集结果addAll,后⼀个⼦任务的结果直接全部添加到

    前⼀个⼦任务结果中

    CH_ID 是⼀个unmodififiableSet集合

    Collectors.toMap()

    Collectors.toSet()

    Collectors.toCollection() :⽤⾃定义的实现Collection的数据结构收集

    Collectors.toCollection(LinkedList::new)

    Collectors.toCollection(CopyOnWriteArrayList::new)

    Collectors.toCollection(TreeSet::new)

    1. 拼接函数Collectors.joining
    • 共有三个重载方法

    //3种重载⽅法

    Collectors.joining()

    Collectors.joining(“param”)

    Collectors.joining(“param1”, “param2”, “param3”)

    该⽅法可以将Stream得到⼀个字符串, joining函数接受三个参数,分别表示 元素之间的连

    接符、前缀和后缀。

    List<String> list=Arrays.asList("abc","bcd","cmd");
    String result = list.stream().collect(Collectors.joining(","));
    System.out.println(result);
    
    • 添加前缀和后缀
    String result = Stream.of("springboot", "mysql", "html5",
                              "css3").collect(Collectors.joining(",", "[", "]"));
    
    1. jdk8里面partitioningBy分组
    • Collectors.partitioningBy分组,key是boolean类型
    //源码====predicate是断言
    public static <T>
        Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super
                                                              T> predicate) {
        return partitioningBy(predicate, toList());
    }
    
    • 需求:根据list进行分组,字符串长度大于4的为一组,其他为一组。
    List<String> list = Arrays.asList("java", "springboot","HTML5","nodejs","CSS3");
    Map<Boolean, List<String>> result =list.stream().collect(partitioningBy(obj -> obj.length() > 4));
    
    1. group By分组
    • Collectors.groupingBy()

    • 需求:根据学生所在的省份,进行分组

    List<Student> students = Arrays.asList(new Student("⼴东", 23), new Student("⼴东", 24), new Student("⼴东", 23),new Student("北京", 22), new Student("北京", 20), new Student("北京", 20),new Student("海南", 25));
    Map<String, List<Student>> listMap =students.stream().collect(Collectors.groupingBy(obj ->obj.getProvince()));
    listMap.forEach((key, value) -> {
        System.out.println("========");
        System.out.println(key);
        value.forEach(obj -> {
            System.out.println(obj.getAge());
        });
    });
    class Student {
        private String province;
        private int age;
        public String getProvince() {
            return province;
        }
        public void setProvince(String province) {
            this.province = province;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public Student(String province, int age) {
            this.age = age;
            this.province = province;
        }
    }
    
    1. Collectors.counting()统计
    • 需求:统计各个省份的人数
    List<Student> students = Arrays.asList(new Student("⼴东", 23), new Student("⼴东", 24), new Student("⼴东", 23),new Student("北京", 22), new Student("北京", 20), new Student("北京", 20),new Student("海南", 25));
    Map<String, Long> listMap =students.stream().collect(Collectors.groupingBy(Student::getProvince,Collectors.counting()));
    listMap.forEach((key, value) -> {System.out.println(key+"省⼈数有
                                                        "+value);});
    
    1. 统计平均值,最大值,最小值等。
    • Collectors.summarizing()
    public static <T> Collector<T, ?, IntSummaryStatistics>
        summarizingInt(ToIntFunction<? super T> mapper) { return new
        CollectorImpl<T, IntSummaryStatistics, IntSummaryStatistics>(
        IntSummaryStatistics::new,
        (r, t) -> r.accept(mapper.applyAsInt(t)),
        (l, r) -> { l.combine(r); return l; }, CH_ID);
                                                        }
    
    • 分类

    summarizingInt

    summarizingLong

    summarizingDouble

     List<Student> students = Arrays.asList(new Student("⼴东", 23), new
    Student("⼴东", 24), new Student("⼴东", 23),new Student("北京", 22), new
    Student("北京", 20), new Student("北京", 20),new Student("海南", 25));
    IntSummaryStatistics summaryStatistics =
    students.stream().collect(Collectors.summarizingInt(Student::getAge));
    System.out.println("平均值:" + summaryStatistics.getAverage());
    System.out.println("⼈数:" + summaryStatistics.getCount());
    System.out.println("最⼤值:" + summaryStatistics.getMax());
    System.out.println("最⼩值:" + summaryStatistics.getMin());
    System.out.println("总和:" + summaryStatistics.getSum());
    class Student {
     private String province;
     private int age;
     public String getProvince() {
     return province;
     }
     public void setProvince(String province) {
     this.province = province;
     }
     public int getAge() {
     return age;
     }
     public void setAge(int age) {
     this.age = age;
     }
     public Student(String province, int age) {
     this.age = age;
     this.province = province;
     }
    }
    

    jdk8新内存空间Metaspace

    1. HostSpot虚拟机新增了内存空间Metaspace

    2. jdk8中的永久代被取消了。

    JVM内存知识 在JDK8之前的HotSpot JVM,有个区域叫做“永久代(permanent generation), 通过
    在命令⾏设置参数-XX:MaxPermSize来设定永久代最⼤可分配的内存空间
    如果JDK8⾥⾯设置了PermSize 和 MaxPermSize 会被忽略并给出警告

    1. 永久代的作用

    该块内存主要是被JVM⽤来存放 class 和 mate 信息的,当 class 被加载 loader 的时候就会

    被存储到该内存区中,如⽅法的编译信息及字节码、常量池和符号解析、类的层级信息,字段,名

    字等

    永久代空间不够,类信息太多,会报oom

    1. jdk8的处理

    jdk8的修改 JDK8 HotSpot JVM 使⽤本地内存来存储类元数据信息,叫做 元空间(Metaspace)

    在默认情况下Metaspace的⼤⼩只与本地内存⼤⼩有关

    常⽤的两个参数 -XX:MetaspaceSize=N 指Metaspace扩容时触发FullGC的初始化阈值

    -XX:MaxMetaspaceSize=N 指⽤于限制Metaspace增⻓的上限,防⽌因为某些情况导致

    Metaspace⽆限的使⽤本地内存

    不管两个参数如何设置,都会从20.8M开始,然后随着类加载越来越多不断扩容调整直到最⼤

    1. 查看Metaspace大小命令

    jstat -gc pid MC: current metaspace capacity MU: mateaspace utilization

    MC:Metaspace的容量空间

    MU:Metaspace的已经使用空间。

    jdk7里面的新特性try-with-resources

    1. 在try( …)⾥声明的资源,会在try-catch代码块结束后⾃动关闭掉
    2. 旧的写法
    public static void main(String[] args) throws IOException {
        String path = "/Users/jack/Desktop/t.txt";
        test(path);
    }
    private static void test(String filepath) throws FileNotFoundException {
        OutputStream out = new FileOutputStream(filepath);
        try {
            out.write((filepath+"可以学习java架构课程").getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    1. 新的写法
    private static void test(String filepath){
        try(OutputStream out = new FileOutputStream(filepath);) {
            out.write((filepath+"可以学习java架构课程").getBytes());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    1. 注意点

    1、实现了AutoCloseable接⼝的类,在try()⾥声明该类实例的时候,try结束后⾃动调⽤的
    close⽅法,这个动作会早于finally⾥调⽤的⽅法
    2、不管是否出现异常,try()⾥的实例都会被调⽤close⽅法

    3、try⾥⾯可以声明多个⾃动关闭的对象,越早声明的对象,会越晚被close掉

    展开全文
  • JDK8 Stream 详细使用

    千次阅读 多人点赞 2018-09-03 23:58:53
    JDK8 管道 Stream 详细使用介绍   Stream 的获取 ① 通过集合Collection获取 List&lt;Integer&gt; list = new ArrayList&lt;Integer&gt;(Arrays.asList(1,2,3,4,5)); Stream&lt;Integer&...

    JDK8 管道 Stream 详细使用介绍

     

    Stream 的获取

    ① 通过集合Collection获取

    List<Integer> list = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5));
    Stream<Integer> stream = list.stream();

    ② 通过数组获取

    String[] array = {"are","you","ok"};
    Stream<String> stream = Arrays.stream(array);
    //对于基本类型数组的处理
    int[] array = {1,2,3,4,5};
    Stream<Integer> stream = Arrays.stream(array).boxed();    
    //Arrays.stream(array)获取的是一个IntStream对象,boxed 方法用于将目前 Stream 中的基本类型装箱

    ③ 直接通过值获取

    Stream<String> stream = Stream.of("are","you","ok");

     


    Stream 常用管道操作

    1) 筛选 filter

    filter函数接收一个Lambda表达式作为参数,该表达式返回 boolean,在执行过程中,流将元素逐一输送给filter,并筛选出执行结果为 true 的元素;

    //筛选出列表中的非空项
    List<String> list = Arrays.asList("are","you","","ok");
    List<String> filted = list.stream()
                          .filter(x-> !x.empty())
                          .collect(Collectors.toList());

    2) 去重 distinct

    //去除列表中的重复元素
    List<String> list = Arrays.asList("are","you","you","ok");
    List<String> distincted = list.stream()
                              .distinct()
                              .collect(Collectors.toList());

    3) 截取 limit

    截取流的前N个元素:

    //获取Stream的前3个值
    List<String> list = Arrays.asList("are","you","fucking","ok");
    List<String> distincted = list.stream()
                              .limit(3);
                              .collect(Collectors.toList());

    4) 跳过 skip

    跳过流的前n个元素:

    List<String> list = Arrays.asList("are","you","fucking","ok");
    List<String> distincted = list.stream()
                              .skip(2);
                              .collect(Collectors.toList());

    5) 映射 map

    对流中的每个元素执行一个函数,使得元素转换成另一种类型输出。流会将每一个元素输送给map函数,并执行map中的Lambda表达式,最后将执行结果存入一个新的流中。 
    如:将 list 中每一个 Integer类型元素自增后转化为 String类型

    //将集合中的每一个元素+1,并转为字符串
    List<Integer> list = Arrays.asList(1,2,3,4,5);
    List<String> result = list.stream()
                          .map(x->String.valueOf(++x))
                          .collect(Collectors.toList());
    //统计集合中>3的元素数量
    int result = list.stream().filter(x -> x > 3).count();

    6) 合并多个流 flatMap

    List<String> list1 = .....
    List<String> list2 = ...
    List<List<String>> list = Arrays.asList(list1,list2); 
    //将list中的list1,list2合并为一个List<String>
    List<String> listsum = list.stream()
                               .flatMap(List::stream)
                               .collect(Collectors.toList());

    以下一个实际的应用例子:列出 list 中各不相同的单词;

    List<String> list = new ArrayList<String>();
    list.add("I am a boy");
    list.add("I love the girl");
    list.add("But the girl loves another girl");
    
    list.stream().map(line->line.split(" "))    //将每一个项分词,并映射为数组
                 .flatMap(Arrays::stream)       //将每一个分项数组组合并到主流中,形成一个包含所有分项数组的总数组流
                 .distinct()                   //去重
                 .forEach(System.out::println);   //打印

    7)匹配元素

     ①是否匹配任一元素:anyMatch

    anyMatch用于判断流中是否存在至少一个元素满足指定的条件,这个判断条件通过Lambda表达式传递给anyMatch,执行结果为boolean类型。 

    //判断流中是否含有>10的项
    List<Integer> list = Arrays.asList(1,2,3,4,5,6);
    boolean result = list.stream()
                         .anyMatch(x->x>10);

    ② 是否匹配所有元素:allMatch

    allMatch用于判断流中的所有元素是否都满足指定条件,这个判断条件通过Lambda表达式传递给anyMatch,执行结果为boolean类型。 

    //判断流中是否全部>5
    List<Integer> list = Arrays.asList(1,2,3,4,5,6);
    boolean result = list.stream()
                         .allMatch(x->x>5);

    ③ 是否未匹配所有元素:noneMatch

    noneMatch与allMatch恰恰相反,它用于判断流中的所有元素是否都不满足指定条件:

    //判断流中是否 全部不满足 >5
    List<Integer> list = Arrays.asList(1,2,3,4,5,6);
    boolean result = list.stream()
                         .noneMatch(x->x>5);

    8)获取元素

    ①获取任一元素 :findAny

    findAny从流中随机选出 一个元素出来,它返回一个Optional类型的元素。

    List<Integer> list = Arrays.asList(1,2,3,4,5,6);
    Optional<Integer> result = list.stream().findAny();
    
    if(result.isPresent())
      Integer randValue = result.get();
    //or:
      Integer randValue = result.orElse(0);
    
    //合并的调用方式
    Integer randValue = list.stream().findAny().orElse(0);

    ② 获取第一个元素:findFirst

    Optional<Integer> result = list.stream().findFirst();

    Optional 对象介绍

    Optional是Java8新加入的一个容器,这个容器只存1个或0个元素,它用于防止出现NullpointException,它提供如下方法:

    • isPresent() 
      判断容器中是否有值。
    • ifPresent(Consume lambda) 
      容器若不为空则执行括号中的Lambda表达式。
    • T get() 
      获取容器中的元素,若容器为空则抛出NoSuchElement异常。
    • T orElse(T other) 
      获取容器中的元素,若容器为空则返回括号中的默认值

    9) 归约统计

    归约是将集合中的所有元素经过指定运算,折叠成一个元素输出,如:求最值、平均数等,这些操作都是将一个集合的元素折叠成一个元素输出;

    //获取一个整型列表的最大值,最小值
    Random random = new Random();
    List<Integer> list = random.ints(1,100).limit(50).boxed().collect(Collectors.toCollection(ArrayList::new));
    int max = list.stream().max(Integer::compare).orElse(-1);   //获取最大值
    int min = list.stream().min(Integer::compare).orElse(-1);   //获取最小值
    
    //获取一个Bean列表的最大值对象,最小值对象,使用自定义的 Comparator
    List<Bean> beans = new ArrayList<>();
    for(int i = 0; i < 50; i++){
        beans.add(new Bean(String.valueOf(random.nextInt(10000)),random.nextInt(20)));
    }
    Bean maxBean = beans.stream().max(Comparator.comparingInt(Bean::getOrderNum)).get();   
    Bean mixBean = beans.stream().min((bean1, bean2) ->{                       //使用自定义的 lambda 表达式
         if(bean1.getId() == null){
             bean1.setOrderNum(0);
         }
         if(bean2.getId() == null){
             bean2.setOrderNum(0);
         }
         return Integer.compare(bean1.getOrderNum(), bean2.getOrderNum());
    }).get();
    
    
    //使用基于数据流的方式,将流装载相应的 SummaryStatistics 来进行归约计算,可以实现更多的操作;
    IntSummaryStatistics stats = list.stream().mapToInt(x -> x). summaryStatistics();
    int max = stats.getMax());        //获取最大值
    int min = stats.getMin());        //获取最小值
    double sum =  stats.getSum());    //获取总值
    double avg = stats.getAverage());  //获取平均值
    long count = stats.getCount();     //获取总数量

    10) 遍历流 forEach

    数据流提供了新的forEach方法遍历该流中的每个元素,方法参数为一个Lambda表达式,用于对每一个遍历的元素执行的操作;

    //输出10个随机数
    Random random = new Random();
    random.ints().limit(10).forEach(System.out::println);

    11) 排序 sorted

    sorted方法用来流排序,默认升序排布,可以使用一个 Comparator 作为参数来实现自定义排序;

    //输出10个排序好的随机数
    Random random = new Random();
    random.ints().limit(10).sorted().forEach(System.out::println);   //升序
    random.ints().limit(10).sorted(x1,x2 -> Integer.compare(x2, x1)).forEach(System.out::println);   //降序

    12)parallelStream 并行处理

    parallelStream是流 进行并行处理的替代方案,parallelStream 的底层实现为 ForkJoin 线程池,JDK8 为为 parallelStream 提供了一个通用的线程池,对于代码实际运行时的 parallelStream 线程数量是不可控的,但是可以通过设置 JVM 运行参数 -Djava.util.concurrent.ForkJoinPool.common.parallelism=N (N为线程数量)来调整 JVM ForkJoinPool 的线程数量;

    List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
    //get count of empty string
    int count = strings.parallelStream().filter(string -> string.isEmpty()).count();

     


    数值流的使用

    采用Stream 的 redure 方法 进行数值归约操作会涉及到基本数值类型和引用数值类型之间的装箱、拆箱操作,因此效率较低;
    此时最好是将当流操作为纯数值操作时,这样使用数值流能获得较高的效率;

    StreamAPI提供了三种数值流:IntStream、DoubleStream、LongStream;

    1)将 Stream 转换成数值流

    StreamAPI 提供了将普通流转换成数值流的三种方法:mapToInt、mapToDouble、mapToLong(参数:相应的转化Lambda表达式);

    将数值流转化为Stream 的方法:boxed;

    List<Double> list = Arrays.asList(2.3,2.4,2.5,2.7,2.8);
    
    //普通Stream转为数值Stream
    DoubleStream doubles = list.stream().mapToDouble(x->x);    //转化为DoubleStream
    IntStream ints = list.stream().mapToInt(x->Integer.parseInt(String.format("%.0f",x))); //转化为IntStream,同时进行取舍操作
    
    //数值Stream转为普通Stream
    Stream stream = list.boxed();

    2)数值流的数值计算

    每种数值流都提供了数值计算函数,如max、min、sum、avg等。 

    List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
    
    OptionalInt max = list.stream().max();
    int max_value = max.orElse(0);
    OptionalInt sum = list.steam().sum();
    iny sum_value = sum.orElse(0);

    由于数值流可能为空,并且给空的数值流计算最大值是没有意义的,因此max函数返回OptionalInt,它是Optional的一个子类,能够判断流是否为空,并对流为空的情况作相应的处理。 
    此外,mapToInt、mapToDouble、mapToLong进行数值操作后的返回结果分别为:OptionalInt、OptionalDouble、OptionalLong

     


    Stream 转换为 Collection、Array、String

    Stream 可以通过 Collector 收集器,将其转化为 Array,Collection,Map,String;

    ① Stream -> 数组

    //普通转换
    Stream<String> stream = Stream.of("are","you","ok");
    String[] array = stream().toArray();
    
    //涉及拆箱、装箱操作的转换
    Stream<Integer> stream = Stream.of(1,2,3,4,5,6);
    int[] array = stream.mapToInt(x->x).toArray();
    Integer[] array = stream.toArray(Integer[]::new);
    
    //将 List<Inetegr> 转化为 String[]
    List<Integer> list = Arrays.asList(1,2,3,4,5);
    String[] array = list.stream().map(String::valueOf).toArray(String[]::new);

    ② Stream -> List

    List<Integer> list1 = stream.collect(Collectors.toList());
    List<Integer> list2 = stream.collect(Collectors.toCollection(ArrayList::new));

    ③ Stream ->Set

    Set<Integer> set = stream.collect(Collectors.toCollection(Set::new));

    ④ Stream ->Stack

    Stack<Integer> stack = stream.collect(Collectors.toCollection(Stack::new));

    ⑤ Stream ->Map

    Map<Integer, String> map = Stream.of("are","you","ok").collect(Collectors.toMap( s -> s.hashCode(), s -> s));

    ⑥ Stream -> String

    Stream 可以很方便转化为 String,利用这一个特性,可以十分方便地将一个 Collection(List,Set等)转化为使用某个标点符号分隔的字符串;

    //将 List 转化为使用 “,” 分隔的字符串
    List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
    String str = list.stream().map(x->x.toString()).collect(Collectors.joining(","));
    System.out.println(str);
    //输出: 1,2,3,4,5,6,7

     

    对 Map 使用Stream

    虽然 JDK8 的 Stream API 不直接支持 Map,但是我们可以通过对 Map 的 entrySet,keySet,valueColletion 生成 Stream 来进行曲线救国,如下示例:

    Map<Integer,String> map = new HashMap<Integer,String>(){{
           put(1,"are");
           put(2,"you");
           put(3,"ok"); }};
    
    map.entrySet().forEach(System.out::println);  //遍历key-value
    int randomKey = map.keySet().stream().findAny().orElse(-1);  //随机取出一个key
    String values = map.values().stream().distinct().collect(Collectors.joining(","));  //将value去重后组装成使用“,”分隔的字符串

     

    展开全文
  • 试水jdk8 stream

    2018-12-16 20:23:00
    试水jdk8 stream jdk8出来日子不短了,jdk11都出来了,不过用的最多的不过是1.5罢了。 今年终于鼓起勇气认真对待它,在18年记录下学习stream,画上一个圆。 先看个图 Java8中有两大最为重要...

    试水jdk8 stream

    jdk8出来日子不短了,jdk11都出来了,不过用的最多的不过是1.5罢了。

    今年终于鼓起勇气认真对待它,在18年记录下学习stream,画上一个圆。

    先看个图

    Java8中有两大最为重要的改变。第一个是Lambda 表达式;另外一个则是Stream API(java.util.stream.*)。

    说说stream吧。前提得有lambda的基础。

    Stream 是Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用SQL 执行的数据库查询。也可以使用Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

    对stream的操作分为三类。

    1. 创建stream
    2. 中间操作(intermediate operations)
    3. 结束操作(terminal operations):

    流程如下图

    创建stream

    虽然大部分情况下stream是容器调用Collection.stream()方法得到的,但stream和collections有以下不同:

    • 无存储。stream不是一种数据结构,它只是某种数据源的一个视图,数据源可以是一个数组,Java容器或I/O channel等。
    • 为函数式编程而生。对stream的任何修改都不会修改背后的数据源,比如对stream执行过滤操作并不会删除被过滤的元素,而是会产生一个不包含被过滤元素的新stream。
    • 惰式执行。stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行。
    • 可消费性。stream只能被“消费”一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成。
    Stream API是Java 8中加入的一套新的API,主要用于处理集合操作,不过它的处理方式与传统的方式不同,
    称为“数据流处理”。流(Stream)类似于关系数据库的查询操作,是一种声明式操作。比如要从数据库中获取所有id大于1(filter)的用户的名称(map)
    并按照用户的score进行排序(sorted),如果在sql中就会很容易完成,但是在java程序中,在jdk8以前可能要使用很多的if条件,但是在jdk8的stream
    流中,我们可以这样
    @Test
        public void test5() {
            List<String> collect = list.stream()
                    .filter(p -> p.getId() > 1)
                    .sorted(Comparator.comparing(Star::getScore))
                    .map(Star::getName)
                    .collect((Collectors.toList()));
            System.out.println(collect);
        }

     就是这么的容易。

     
     
     
     
    jdk双冒号
    还是比较绕的,看代码就明白了。详细借鉴
    package com.test;
    
    import java.util.Arrays;
    import java.util.List;
    import java.util.function.Consumer;
    
    import org.junit.Test;
    
    public class DoubleColonTest {
        
        public static void myPrint(String str) {
            System.out.println("print value : " + str);
        }
        
        /**
         * 不使用双冒号
         */
        @Test
        public void test1() {
            List<String> list = Arrays.asList("刘德华","黎明","张学友","郭富城");
            list.forEach(p -> myPrint(p));
        }
        
        /**
         * 使用双冒号
         */
        @Test
        public void test2() {
            List<String> list = Arrays.asList("刘德华","黎明","张学友","郭富城");
            list.forEach(DoubleColonTest::myPrint);
        }
        
        /**
         * 类似于双冒号
         */
        @Test
        public void test3() {
            List<String> list = Arrays.asList("刘德华","黎明","张学友","郭富城");
            Consumer<String> methodParam = DoubleColonTest::myPrint;
            list.forEach(methodParam);
        }
        
        /**
         * 类似于双冒号
         */
        @Test
        public void test4() {
            List<String> list = Arrays.asList("刘德华","黎明","张学友","郭富城");
            Consumer<String> methodParam = DoubleColonTest::myPrint;
            list.forEach(p -> methodParam.accept(p));
        }
        
    }

     

     

    完整代码实例

    package com.test;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.Iterator;
    import java.util.List;
    import java.util.stream.Collectors;
    import java.util.stream.Stream;
    
    import org.junit.Before;
    import org.junit.Test;
    
    public class TestStream {
    
        List<Star> list = null;
    
        @Before
        public void before() {
            list = new ArrayList<Star>() {
                {
                    add(new Star(1, "张学友", 11.3));
                    add(new Star(3, "刘德华", 4.3));
                    add(new Star(2, "黎明", 13.3));
                    add(new Star(5, "郭富城", 22.3));
                    add(new Star(4, "范冰冰", 2.3));
                }
            };
        }
    
        /**
         * 遍历方式
         */
        @Test
        public void test1() {
            System.out.println("第一种---------");
            for (Star Star : list) {
                System.out.println(Star);
            }
    
            System.out.println("第二种---------");
            list.forEach(p -> System.out.println(p));
    
            System.out.println("第三种---------");
            list.forEach(System.out::println);
    
            System.out.println("第四种---------");
            Iterator<Star> iterator = list.iterator();
            while (iterator.hasNext()) {
                System.out.println(iterator.next());
            }
    
            System.out.println("第五种---------");
            for (int i = 0; i < list.size(); i++) {
                System.out.println(list.get(i));
            }
    
            System.out.println("第六种---------");
            for (Iterator<Star> it = list.iterator(); it.hasNext();) {
                System.out.println(it.next());
            }
    
            System.out.println("第七种---------");
            for (int i = 0; i < list.size();) {
                System.out.println(list.get(i));
                i++;
            }
    
        }
    
        /**
         * 普通排序
         */
        @Test
        public void test2() {
            Collections.sort(list, new Comparator<Star>() {
                @Override
                public int compare(Star o1, Star o2) {
                    return o1.getScore().compareTo(o2.getScore());
                }
            });
            list.forEach(p -> System.out.println(p));
        }
    
        /**
         * lambda排序
         */
        @Test
        public void test3() {
            Collections.sort(list, (p1, p2) -> p1.getScore().compareTo(p2.getScore()));
            list.forEach(p -> System.out.println(p));
        }
    
        /**
         * streame排序
         */
        @Test
        public void test4() {
            Stream<Star> stream = list.stream().sorted(Comparator.comparing(Star::getScore));// .forEach(p ->
            stream.forEach(p -> System.out.println(p));
            // list.forEach(p -> System.out.println(p));
        }
    
        /**
         * 进行过滤操作
         */
        @Test
        public void test5() {
            List<String> collect = list.stream()
                    .filter(p -> p.getId() > 1)
                    .sorted(Comparator.comparing(p -> p.getScore()))
    //                .sorted(Comparator.comparing(Star::getScore))
                    .map(Star::getName)
                    .collect((Collectors.toList()));
            System.out.println(collect);
        }
    
    }
    
    class Star {
        private Integer id;
        private String name;
        private Double score;
    
        public Double getScore() {
            return score;
        }
    
        public void setScore(Double score) {
            this.score = score;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Star() {
            super();
        }
    
        public Star(Integer id, String name, Double score) {
            super();
            this.id = id;
            this.name = name;
            this.score = score;
        }
    
        @Override
        public String toString() {
            return "Star [id=" + id + ", name=" + name + ", score=" + score + "]";
        }
    
    }

     

    OK,到位,入个门。。。

     
    借鉴的地址
    http://www.nowcode.cn/index.php/2017/02/27/326/
    https://www.jianshu.com/p/ceb7bf515c03
     
     
     
     
     

     

    posted @ 2018-12-16 20:23 陈灬大灬海 阅读( ...) 评论( ...) 编辑 收藏
    展开全文
  • jdk8 stream

    2021-03-08 15:14:49
    jdk8stream流的大致用法 下面展示一些 代码片。 public static void main(String[] args) { ArrayList<User> list1 = new ArrayList<>(); list1.add(new User(8,"张二狗")); list1.add(new User(10...
  • jdk8 Stream特性

    2019-05-01 11:00:39
    streamfilter用法 // '#'表达式的'key值不为空'隐藏条件加在最外层 可提速 criteriaUnit.getQueryUnitList().stream() .filter(queryUnit -> ESQueryUnitScope.UNIT_SCOPE_FIELDS_NOT_EQUAL.equals(...
  • JDK8 stream用法

    2018-06-08 18:51:18
    举例 public static void main(String[] args) { // TODO Auto-generated method stub List&... Stream&amp;amp;amp;lt;Person&amp;amp;amp;gt; s = l.stream(); s.forEach(P-&
  • JDK8 Stream 数据流效率分析

    万次阅读 多人点赞 2018-09-03 23:26:57
    JDK8 Stream 数据流效率分析   Stream 是Java SE 8类库中新增的关键抽象,它被定义于 java.util.stream (这个包里有若干流类型: Stream&lt;T&gt; 代表对象引用流,此外还有一系列特化流,如 IntStream...
  • 1、说明 本文代码基本参照JDK的实现,类名,...同时JDK stream内还有很多操作,如filter,collect,flatmap等,有时也称操作为算子。 每个sink都有一个accept方法,用于接收元素。为说明流实现原理,假设filter的sin
  • JDK8 Stream 初识

    2018-11-07 10:23:26
    Stream作为jdk8的一种重要特性,我们应该了解多一些。 为什么会有Stream? 在Stream出现之前,我们对集合中的元素进行一些操作需要先遍历每个元素再进行操作。如: LinkedHashMap&amp;amp;lt;String, ...
  • JDK8 stream操作

    千次阅读 2017-10-12 10:03:12
    * java.util.Stream表示了某一种元素的序列,在这些元素上可以进行各种操作。Stream 操作可以是中 * 间操作,也可以是完结操作。完 结操作会返回一个某种类型的值,而中间操作会返回流对象本身,并且你 * 可以...
  • jdk8 Stream

    2015-07-27 15:07:29
    1. Stream初体验 我们先来看看Java里面是怎么定义Stream的: A sequence of elements supporting sequential and parallel aggregate operations. 我们来解读一下上面的那句话: Stream是元素的集合...
  • 1.简单的filter和map的单独形式 ...list = list.stream().filter(person -> person.getAge() == 20).collect(toList()); 2.map与filter的位置互换 List<String> cidList = userInfoEntitie
  • JDK8 stream操作记录

    2020-04-30 14:38:54
    JDK8 stream一些操作是将函数作为对象传入。 Stream一些方法如map,接受以函数的形式传参:1.传入Lambda函数形式,类似只有一个接口的匿名内部类:(param1,param2)->{ 函数体},2.传入类似System.out::println...
  • Stream 是什么, 能干什么 Stream 实例的创建 Stream 的使用 Stream实例的操作 Stream实例操作结果的聚集
  • Java JDK8 Stream流操作

    2018-08-30 10:52:12
    1、Stream.of(T t); 2、Arrays.stream(strArray); 3、list.stream(); 二、流的操作: List<String> strList= new ArrayList<>(); strList.add("aaa"); strList.add("bbb"); strList.add("ccc");...
  • Stream流是JDK8的新特性,通常用于处理集合。先抛出我遇到的问题,使用Stream的sorted方法时,处理后的集合跟处理前的集合是‘一致的’。就像这样: public class StreamSortTest { // 定义一个商品集合 private ...
  • jdk 8 stream的简单运用

    2018-11-27 15:37:15
    jdk 8 Stream的简单运用 概述 Stream api的介绍网上不少,这里不多说了,本文主要总结一下可能对你有帮助的stream的简单操作,你可以在这些小例子中举一反三得到更多有用的能够简化你代码的写法。文末贴上一些本文...
  • jdk8 stream与parallelStream实现源码阅读

    千次阅读 2019-07-22 23:56:41
    从java 8以后,jdk底层新增了Stream API,使我们写出更简洁、干净的代码来对集合、数组等进行操作,先简单介绍下流的几个概念: Stream(流)是一个来自数据源的元素队列并支持聚合操作 元素是特定类型的对象,...
  • jdk8stream map取对象中某项值的问题

    千次阅读 2019-01-14 21:02:50
    jdk8 Stream map 取对象中某项的值 map 取对象中某项的值 问题 ... List&amp;lt;ScreenWiperResponse&amp;gt; screenWiperList= screenWiperResponseList.stream().map...
  • jdk8 Stream的操作分类

    2021-07-10 22:47:40
    随手记录下,方便以后查看(Stream的中间操作和结束操作图如下) List<String> names = Arrays.asList(... .filter(it -> it.equals("hello")) .map(it -> it.toUpperCase()) .collect(Collectors.toLi
  • jdk8 stream的用法

    2018-09-01 00:33:48
    public class stream { public static void main(String[] args) { List&amp;amp;lt;Person&amp;amp;gt; list = new ArrayList&amp;amp;lt;&amp;amp;gt;(); Person p1 = new Person(); p1....
  • collect4 = list.stream() //.distinct() //根据整个对象去重 //根据对象的某个属性去重:需要下述的辅助方法distinctByKey() .filter(distinctByKey(user -> user.getName())) .collect(Collectors.to...
  • list.stream().filter(complain -> complain.getProduct() == null).forEach(complain -> {})
  • JDK8 Stream 效率如何?

    2021-04-16 00:26:00
    Stream 是Java SE 8类库中新增的关键抽象,它被定义于 java.util.stream (这个包里有若干流类型:Stream<T> 代表对象引用流,此外还有一系列...
  •  平常做一些CRUD业务可能会涉及到查询分页列表的问题,但是有一些业务数据可能不只存在于数据库表之中,可能在ES,mongo,redis等各种数据聚合而成,返回也需要做到有分页效果,因此我们可以利用JDK8的新特性来实现...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 16,890
精华内容 6,756
关键字:

filterjdk8stream