Stream相关API学习使用记录--(一)

一、前言

在以前的工作中,业务中很多时候是需要循环来获取某一个列表中的一些数据,比如获取某一个值做业务逻辑的判断,或者获取其中一部分的数据,如使用状态的标志位等等,这个时候可能很多时候都是使用简单的for循环、Foreach循环或者迭代器等方式,很多时候为了处理业务都是需要循环嵌套循环的。但是在Java8中为集合的相关处理提供了一个更强大的工具,那么就是Stream,在浏览代码的时候看见了其他人的书写,感觉很惊奇(此时自己也很无语,Java8出来这么久了,自己好像好没有意识到它到底添加了那些新的内容,有什么新的特性,简化了那些操作等等),所以自己就对这个东西充满了好奇。

二、 Stream的基础简介

2.1、stream是什么

它是Java8 API添加的一个新的抽象流,它把要处理的元素看做一种流,流在管道中传输,并且可以在管道的节点上进行处理,例如排序,筛选和聚合等操作,可以让人以一种声明的方式来处理数据。
元素流在管道中经过中间操作(intermediate operation)处理,最后由最终操作(terminal operation)得到前面的处理结果。


+------------------------+                +---------+         +-----------+         +--------+        +-------+
| stream of elements +-------->   |filter    +-----> |sorted    +-----> |map    +----> |collect|
+-----------------------+                 +---------+         +-----------+          +--------+      +-------+

2.2、特性

stream是一个来自数据源的元素队列并支持聚合操作:
(1)元素是特定的元素,形成一个队列,但是stream不会存储元素,而是按需计算
(2)数据源可以是集合、数组、I/Ochannel等
(3)集合操作类似链式的SQL,如filter、map、reduce、find、match、sortde等

2.3、流生成方式

2.3.1、串行流

使用stream方式,为集合创建串行流

2.3.2、并行流

使用parallelStream 为集合创建并行流

三、管道节点

3.1、ForEach

Stream提供了新的方法来迭代流中的每一个数据

public class StreamDemoTest {

    private final static Integer MAX_CIRCLE = 100;
    public static void main(String[] args) {
        List<Integer> strList = new ArrayList<>();
        Map<Integer, String> integerMap = new HashMap<>();
        for (int i = 0; i < MAX_CIRCLE; i++) {
            strList.add(i);
            integerMap.put(i, i+"e");
        }
         strList.stream().forEach(s -> System.out.println(s));
    }
}

3.2、map

map方法用于映射每个元素到对应的结果

public class StreamDemoTest {

    private final static Integer MAX_CIRCLE = 100;
    public static void main(String[] args) {
        List<Integer> strList = new ArrayList<>();
        Map<Integer, String> integerMap = new HashMap<>();
        for (int i = 0; i < MAX_CIRCLE; i++) {
            strList.add(i);
            integerMap.put(i, i+"e");
        }
         //strList.stream().forEach(s -> System.out.println(s));
        List<Integer> integerList = strList.stream().map(i -> i * i).collect(Collectors.toList());
        integerList.stream().forEach(s -> System.out.println(s));

    }
}

3.3、filter

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

List<String> stringList = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        // 获取空字符串的数量
        long count = stringList.stream().filter(string ->string!="abc").count();
    //获取不是abc和空的字符串
        List<String> list = stringList.stream().filter(str -> str != "abc"&&str!="").collect(Collectors.toList());

3.4、limit

用于获取指定数量的流

List<String> stringList = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        // 获取空字符串的数量
        long count = stringList.stream().filter(string ->string!="abc").count();
        //限定获取过滤条件后的数量
        List<String> list = stringList.stream().filter(str -> str != "abc"&&str!="").limit(3).collect(Collectors.toList());
        list.stream().forEach(s-> System.out.println(s));

limit的位置可以在filter前面或者后面,只是表示的含义不一样而已。

3.4、sorted

sorted用于对流进行排序

 
public static void main(String[] args) {
        List<String> strList = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        //自然排序
        System.out.println("自然排序");
        strList.stream().sorted().forEach(s -> System.out.println(s));

        System.out.println("倒序排序");
        strList.stream().sorted(Comparator.reverseOrder()).forEach(s -> System.out.println(s));
    }

输出结果已经按照要求进行了排序,默认的是升序排列了,如果想简单的倒序排序,可以使用 Stream<T> sorted(Comparator<? super T> comparator)方法,里面采用Comparator.reverseOrder()进行倒序排序。
如果是自定义的其他的类型,怎么进行排序那?

下面是自定义的一个用户信息的简单实体

class User {
    /**
     * 姓名
     **/
    private String userName;
    /**
     * 英文名称
     **/
    private String englishName;
    /**
     * 年龄
     **/
    private int age;
    /**
     * 住址
     **/
    private String address;
    /**
     * 电话
     **/
    private String tel;

    public User(String userName, String englishName, int age) {
        this.userName = userName;
        this.englishName = englishName;
        this.age = age;
    }

    public User(String userName, String englishName, int age, String address, String tel) {
        this.userName = userName;
        this.englishName = englishName;
        this.age = age;
        this.address = address;
        this.tel = tel;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getEnglishName() {
        return englishName;
    }

    public void setEnglishName(String englishName) {
        this.englishName = englishName;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }

@Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", englishName='" + englishName + '\'' +
                ", age=" + age +
                ", address='" + address + '\'' +
                ", tel='" + tel + '\'' +
                '}';
    }
}
public static void main(String[] args) {
       /* List<String> strList = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        //自然排序
        System.out.println("自然排序");
        strList.stream().sorted().forEach(s -> System.out.println(s));

        System.out.println("倒序排序");
        strList.stream().sorted(Comparator.reverseOrder()).forEach(s -> System.out.println(s));*/

        List<User> userList = new ArrayList<>();
        User user = new User("Angle", "B", 10);
        userList.add(user);
        user = new User("Heni", "G", 39);
        userList.add(user);
        user = new User("Eson", "F", 6);
        userList.add(user);
        user = new User("Cily", "D", 2);
        userList.add(user);
        user = new User("Cily", "G", 6);
        userList.add(user);
        user = new User("Eson", "G", 6);
        userList.add(user);
        System.out.println("正常输出");
        userList.stream().forEach(s-> System.out.println(s.toString()));


        System.out.println("按照名称默认升序排列");
        userList.stream().sorted(Comparator.comparing(User::getUserName)).forEach(s -> System.out.println(s));

        System.out.println("按照名称进行倒序排列");
        userList.stream().sorted(Comparator.comparing(User::getUserName).reversed()).forEach(s -> System.out.println(s));

        System.out.println("多元素排列");
        userList.stream().sorted(Comparator.comparing(User::getUserName).thenComparing(User::getAge).reversed()).forEach(s -> System.out.println(s));

        System.out.println("转换为map");
        userList.stream().collect(Collectors.toMap(User::getUserName,User::getAge,(newValue,oldValue)->newValue)).entrySet().stream().forEach(e-> {
            System.out.println(e.getKey()+"====="+e.getValue());
        });

        System.out.println("过滤以后的");
        userList.stream().filter(e -> e.getUserName().equals("Eson")).sorted(Comparator.comparing(User::getAge).reversed())
                .forEach(e -> System.out.println(e.getUserName() + "======" + e.getAge()));

        System.out.println("如果是重复的key,值转为list");
        Map<String, List<String>> map = userList.stream().collect(Collectors.toMap(User::getUserName,p->{
            List<String> ageList = new ArrayList<>();
            ageList.add(p.getAge() + "");
            return ageList;
        },(List<String> valueNew,List<String> valueOld)->{
            valueNew.addAll(valueOld);
            return valueNew;
        }));
        map.entrySet().stream().forEach(e-> {
            System.out.println(e.getKey()+"====="+e.getValue());
        });
    }

 

输出结果:

正常输出
User{userName='Angle', englishName='B', age=10, address='null', tel='null'}
User{userName='Heni', englishName='G', age=39, address='null', tel='null'}
User{userName='Eson', englishName='F', age=6, address='null', tel='null'}
User{userName='Cily', englishName='D', age=2, address='null', tel='null'}
User{userName='Cily', englishName='G', age=6, address='null', tel='null'}
按照名称默认升序排列
User{userName='Angle', englishName='B', age=10, address='null', tel='null'}
User{userName='Cily', englishName='D', age=2, address='null', tel='null'}
User{userName='Cily', englishName='G', age=6, address='null', tel='null'}
User{userName='Eson', englishName='F', age=6, address='null', tel='null'}
User{userName='Heni', englishName='G', age=39, address='null', tel='null'}
按照名称进行倒序排列
User{userName='Heni', englishName='G', age=39, address='null', tel='null'}
User{userName='Eson', englishName='F', age=6, address='null', tel='null'}
User{userName='Cily', englishName='D', age=2, address='null', tel='null'}
User{userName='Cily', englishName='G', age=6, address='null', tel='null'}
User{userName='Angle', englishName='B', age=10, address='null', tel='null'}
多元素排列
User{userName='Heni', englishName='G', age=39, address='null', tel='null'}
User{userName='Eson', englishName='F', age=6, address='null', tel='null'}
User{userName='Cily', englishName='G', age=6, address='null', tel='null'}
User{userName='Cily', englishName='D', age=2, address='null', tel='null'}
User{userName='Angle', englishName='B', age=10, address='null', tel='null'}

可以看出来,整个排序是相当的简单了,不需要自己的类继承comparable,也不需要自己扩展排序comparator了。
对于map类型格式的数据。可以对键排序或者值排序

 1 public static void main(String[] args) {
 2         Map<String, String> map = new LinkedHashMap<String, String>();
 3         map.put("12", "ddd");
 4         map.put("23", "eee");
 5         map.put("34", "ddw");
 6         map.put("21", "ecc");
 7 
 8         System.out.println("根据值排序");
 9         map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getValue)).forEach(e -> {
10             String key = e.getKey();
11             String value = e.getValue();
12             System.out.println("键值"+key+"值"+value);
13         });
14         System.out.println("根据键排序");
15         map.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getKey)).forEach(e -> {
16             //System.out.println(e.toString());
17             String key = e.getKey();
18             String value = e.getValue();
19             System.out.println("键值"+key+"值"+value);
20         });
21 }

输出的结果:

根据值排序
键值12值ddd
键值34值ddw
键值21值ecc
键值23值eee
根据键排序
键值12值ddd
键值21值ecc
键值23值eee
键值34值ddw

综合看下来,使用对应的Stream比使用平常简单的循环而言代码量少了很多。

posted @ 2018-11-22 19:33  八月的狮子座  阅读(507)  评论(0编辑  收藏  举报