java基础复习(3)

时间:2020-07-22 01:54:05   收藏:0   阅读:136

写在前面

前面学习了Lambda表达式,现在来学习一下根据Lambda表达式衍生出的Stream流和方法引用。

Stream流

引子

一提到流,可能都只会想到IO流。实际上,流不一定是IO流,今天就来学习一下Stream流。首先我们来看一段传统的集合过滤代码:

        // 创建一个List集合,存储姓名
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");

        // 对集合中的元素进行过滤,只要以张开头头的元素都存到一个新的集合中
        List<String> listA = new ArrayList<>();
        for (String s : list) {
            if(s.startsWith("张")){
                listA.add(s);
            }
        }
        // 对listA集合进行过滤,只要姓名长度为3的人,再存到一个新集合中
        List<String> listB = new ArrayList<>();
        for (String s : listA) {
            
            if (s.length() == 3) {
                listB.add(s);
            }
        }
        // 遍历listB集合
        for (String s : listB) {
            System.out.println("s = " + s);
        }

在这段代码中,我们先选出了姓张的,再选出了姓名长度为3的,最后使用增强for循环进行了输出。可以看到代码还是很多的。那么我们如果使用Stream流呢?

        // 创建一个List集合,存储姓名
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");
        // 对集合中的元素进行过滤,只要以张开头头的元素都存到一个新的集合中
        // 对listA集合进行过滤,只要姓名长度为3的人,再存到一个新集合中
        // 遍历listB集合
        list.stream()
                .filter(name -> name.startsWith("张"))
                .filter(name -> name.length() == 3)
                .forEach(name -> System.out.println(name));

可以看到,我们的代码被极大简化了。这就是结合了Stream流和Lambda表达式给我们带来的编程便利。

获取Stream流

既然这东西这么好,那我们如何获取和使用呢?这里我们学习以下两种获取方法:

  1. 使用集合直接获取
  2. 使用Stream.of静态方法获取。

直接上例子看看:

    public static void main(String[] args) {
        // 把集合转换成Stream流
        List<String> list = new ArrayList<>();
        Stream<String> stream1 = list.stream();
        Set<String> set = new HashSet<>();
        Stream<String> stream2 = set.stream();
        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();
        // 获取键值对(键与值的映射关系 entrySet)
        Set<Map.Entry<String, String>> entries = map.entrySet();
        Stream<Map.Entry<String, String>> stream5 = entries.stream();

        // 把数组转换为Stream流
        Stream<Integer> stream6 = Stream.of(1, 2, 3, 4, 5);
        // 可变参数可以传递数组
        Integer[] arr = {1,2,3,4,5};
        Stream<Integer> stream7 = Stream.of(arr);
        String[] arr2 = {"a","bb","cccc"};
        Stream<String> stream8 = Stream.of(arr2);
    }

可以看到,Stream流的获取还是十分简单的。那么我们可以用Stream流做到什么呢?

Stream流里的常用方法

首先要了解,Stream流的方法有两种,一种叫延迟方法(即返回的还是Stream接口自身),一种叫终结方法,返回的类型就不再是Stream接口自身了。

方法引用

引子

上面我们的使用,实际上已经十分简单了,但能不能更简单呢?可以看到有时候我们的Lambda表达式都只用了一句话,比如下面的这个:

.forEach(name -> System.out.println(name));

这里面的name实际上没有任何意义,只是我们定义的一个形参而已。我们想要的就是输出这个形参罢了。那么我们可以写成下面这样:

.forEach(System.out::println);

是不是更加简单了呢?

介绍和使用

这里出现了一个新的符号,双冒号。学过C++的可能会知道,这个符号在C++里叫做作用域符,有一种用法和上面也很像,如类::变量。但在java中这个叫做引用运算符,如果在Lambda表达式中要表达的函数方法已经存在,那么就可以使用这个符号来调用他。

事实上,我们自己定义的方法也可以用,比如上面我们提到的collect方法,我们也可以用方法引用这么写:

        Map<String, Integer> map = list1.stream().
                collect(Collectors.toMap(Person::getName, Person::getAge));

看起来是不是要简单的多了呢。

小结

方法引用的使用方法和场景多种多样,这里只介绍最基本的用法,具体的就请在日后使用到时再了解吧。

总结

这里学习的这些,都是JDK8里的新特性。通过这些新特性的学习,我们可以让代码更加的优雅了。

评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!