logo头像

分享技术,品味人生

Java核心基础之Stream

Java8带来了很多新特性,如函数式编程、接口默认实现,这边主要介绍Stream流式处理,让代码更简洁高效!

前言

Stream技术主要依赖了泛型和函数式编程,让编译器更智能,编译后的asm代码应该还是一大坨的循环、判断,至少让我们的编码工作简单了不少!也更不易理解了~

Stream的三种创建

有三种方式,stream的创建、list或数组取得流,及通过supplier获得;

Stream.of

Stream<String> stream = Stream.of("A", "B", "C", "D");
stream.forEach(System.out::println);
        
Stream<UserBean> userBeanStream = Stream.of(new UserBean(1, "AKB001", "gilbert"),
                new UserBean(2, "AKB002", "apple"),
                new UserBean(4, "AKB004", "dog"),
                new UserBean(5, "AKB005", "egg"),
                new UserBean(6, "AKB006", "frog"),
                new UserBean(6, "AKB006", "banana"),
                new UserBean(7, "AKB007", "google"),
                new UserBean(3, "AKB003", "cat"));
userBeanStream.forEach(userBean -> System.out.println(userBean.getUserName()));

集合创建Stream

Stream<String> stream1 = Arrays.stream(new String[] { "A", "B", "C" });
Stream<String> stream2 = Arrays.asList("X", "Y", "Z").stream();
stream1.forEach(System.out::println);
stream2.forEach(System.out::println);

基于Supplier

class Fibonacci implements Supplier{
    long i=0, j=1;
    @Override
    public Object get() {
        long temp = i;
        i+= j;
        j = temp;
        return i;
    }
}

@Test
void testStream1() {
    Stream<Long> natual = Stream.generate(new Fibonacci());
    natual.limit(20).forEach(System.out::println);

}

Stream的常用api

本文主要展示流式处理中常见的集合多种不同场景的处理,如:

  • 过滤,filter
  • 去重,distinct
  • 限定,limit
  • 遍历,foreach,这里还用到了方法引入的新特性,跟c#的代码风格很像

过滤 filter

通过函数式编程,可以简单的使用变量进行布尔判断,如文本匹配、长度判断等等。

//这里用到了过滤、遍历
@Test
void testStream1() {
    List<String> list = Arrays.asList("你好", "我好", "大家好", "大好大", "hello world","thanks");
    stream.filter(str -> str.contains("好"))
        .forEach(System.out::println);
}

注意:list可以生成多次的stream反复执行,但一个stream只能运行一次,类似文件指针到底而没有自动回退!

去重 distinct

//通过distinct方法进行去重
@Test
void testStream2() {
    List<String> list = Arrays.asList("你好","你好", "我好", "大家好", "大好大", "hello world","thanks");
    list.stream().filter(str -> str.contains("好"))
        .distinct()
        .forEach(System.out::println);
}

限定返回数量limit

@Test
void testStream2() {
    List<String> list = Arrays.asList("你好", "我好", "大家好", "大好大", "hello world","thanks");
    list.stream().filter(str -> str.contains("好"))
        .limit(2)
        .forEach(System.out::println);
}

转换map

//范例:取出带有好,并在尾部加上两个感叹号
@Test
void testStream2() {
    List<String> list = Arrays.asList("你好", "我好", "大家好", "大好大", "hello world","thanks");
    list.stream().filter(str -> str.contains("好"))
        .map(s->s.concat("!!"))
        .forEach(System.out::println);
}

排序

基于Collections的排序

方法一:Bean实现Comparable接口,Collection或List都可以直接用sort调用

   class UserBean implements Comparable<UserBean>{
        private int userId;
        private String workId;
        private String userName;

        public UserBean(int userId, String workId, String userName) {
            this.userId = userId;
            this.workId = workId;
            this.userName = userName;
        }
        //这里有getset,略过

        @Override
        public int compareTo(UserBean o) {
            return this.getUserName().compareTo(o.getUserName());
        }
    }


@Test
void testStream1() {
    // 基础信息准备
    Stream<UserBean> userBeanStream = Stream.of(new UserBean(1, "AKB001", "gilbert"),
                                                new UserBean(2, "AKB002", "apple"),
                                                new UserBean(4, "AKB004", "dog"),
                                                new UserBean(5, "AKB005", "egg"),
                                                new UserBean(6, "AKB006", "frog"),
                                                new UserBean(6, "AKB006", "banana"),
                                                new UserBean(7, "AKB007", "google"),
                                                new UserBean(3, "AKB003", "cat"));
    List<UserBean> list = userBeanStream.collect(Collectors.toList());
    Collections.sort(list);
    list.sort(null); //同Collection.sort
    Comparator<UserBean> comparator = (userBean1,userBean2) -> userBean1.getUserName().compareTo(userBean2.getUserName());

    Collections.sort(list);
    list.sort(comparator);

}

方法二:用比较器

   class UserBean implements Comparable<UserBean>{
        private int userId;
        private String workId;
        private String userName;

        public UserBean(int userId, String workId, String userName) {
            this.userId = userId;
            this.workId = workId;
            this.userName = userName;
        }
        //这里有getset,略过

        @Override
        public int compareTo(UserBean o) {
            return this.getUserName().compareTo(o.getUserName());
        }
    }


@Test
void testStream1() {
    // 基础信息准备
    Stream<UserBean> userBeanStream = Stream.of(new UserBean(1, "AKB001", "gilbert"),
                                                new UserBean(2, "AKB002", "apple"),
                                                new UserBean(4, "AKB004", "dog"),
                                                new UserBean(5, "AKB005", "egg"),
                                                new UserBean(6, "AKB006", "frog"),
                                                new UserBean(6, "AKB006", "banana"),
                                                new UserBean(7, "AKB007", "google"),
                                                new UserBean(3, "AKB003", "cat"));
    List<UserBean> list = userBeanStream.collect(Collectors.toList());

    Comparator<UserBean> comparator = (userBean1,userBean2) -> userBean1.getUserName().compareTo(userBean2.getUserName());
    Collections.sort(list, comparator);
    Collections.reverse(list);

}

基于Stream的排序

同Collections操作一致,也有两种做法

方法一:实现comparable接口

class UserBean implements Comparable<UserBean>{
    private int userId;
    private String workId;
    private String userName;

    public UserBean(int userId, String workId, String userName) {
        this.userId = userId;
        this.workId = workId;
        this.userName = userName;
    }
    //这里有getset,略过

    @Override
    public int compareTo(UserBean o) {
        return this.getUserName().compareTo(o.getUserName());
    }
}


@Test
void testStream1() {
    // 基础信息准备
    Stream<UserBean> userBeanStream = Stream.of(new UserBean(1, "AKB001", "gilbert"),
                                                new UserBean(2, "AKB002", "apple"),
                                                new UserBean(4, "AKB004", "dog"),
                                                new UserBean(5, "AKB005", "egg"),
                                                new UserBean(6, "AKB006", "frog"),
                                                new UserBean(6, "AKB006", "banana"),
                                                new UserBean(7, "AKB007", "google"),
                                                new UserBean(3, "AKB003", "cat"));
    List<UserBean> list = userBeanStream.collect(Collectors.toList());

    //取得流、排序
    List<UserBean> sortedList = list.stream().sorted().collect(Collectors.toList());
    sortedList.forEach(userBean -> System.out.println("sortList:" + userBean.getWorkId() + "," + userBean.getUserName()));
}

方法二:使用comparator比较器

class UserBean{
    private int userId;
    private String workId;
    private String userName;

    public UserBean(int userId, String workId, String userName) {
        this.userId = userId;
        this.workId = workId;
        this.userName = userName;
    }
    //这里有getset,略过
}


@Test
void testStream1() {
    // 基础信息准备
    Stream<UserBean> userBeanStream = Stream.of(new UserBean(1, "AKB001", "gilbert"),
                                                new UserBean(2, "AKB002", "apple"),
                                                new UserBean(4, "AKB004", "dog"),
                                                new UserBean(5, "AKB005", "egg"),
                                                new UserBean(6, "AKB006", "frog"),
                                                new UserBean(6, "AKB006", "banana"),
                                                new UserBean(7, "AKB007", "google"),
                                                new UserBean(3, "AKB003", "cat"));
    List<UserBean> list = userBeanStream.collect(Collectors.toList());

    //用函数式编程植入比较器
    List<UserBean> sortedList = list.stream()
                .sorted((userBean1,userBean2) -> userBean1.getUserName().compareTo(userBean2.getUserName()))
                .collect(Collectors.toList());
    //Comparator<UserBean> comparator = (userBean1,userBean2) -> userBean1.getUserName().compareTo(userBean2.getUserName());
    //反序可以调用comparator的reversed方法,或在方法返回值乘以-1
    sortedList.forEach(userBean -> System.out.println("sortList:" + userBean.getWorkId() + "," + userBean.getUserName()));
    
    
    
    //备注,使用Comparator的静态方法也是不错的方式!也支持链式操作!
    /*
    List<UserBean> sortedList = list.stream()
                .sorted(Comparator.comparing(UserBean::getUserName).reversed())
                .collect(Collectors.toList());
    */
}

其他操作

分组

Stream<UserBean> userBeanStream = Stream.of(new UserBean(1, "AKB001", "gilbert"),
                                            new UserBean(2, "AKB002", "apple"),
                                            new UserBean(4, "AKB004", "dog"),
                                            new UserBean(5, "AKB005", "egg"),
                                            new UserBean(6, "AKB006", "frog"),
                                            new UserBean(8, "AKB006", "banana"),
                                            new UserBean(7, "AKB007", "google"),
                                            new UserBean(3, "AKB003", "cat"));
List<UserBean> list = userBeanStream.collect(Collectors.toList());

Map<String,List<UserBean>> groupByMap = list.stream().collect(Collectors.groupingBy(UserBean::getWorkId));
groupByMap.forEach((k,v) -> System.out.println(k+"," + v));

//-----------------------------------------------------------
AKB002,[cool.gongju.spring5.TestStream$UserBean@5579bb86]
AKB003,[cool.gongju.spring5.TestStream$UserBean@5204062d]
AKB001,[cool.gongju.spring5.TestStream$UserBean@4fcd19b3]
AKB006,[cool.gongju.spring5.TestStream$UserBean@376b4233, cool.gongju.spring5.TestStream$UserBean@2fd66ad3]
AKB007,[cool.gongju.spring5.TestStream$UserBean@5d11346a]
AKB004,[cool.gongju.spring5.TestStream$UserBean@7a36aefa]
AKB005,[cool.gongju.spring5.TestStream$UserBean@17211155]

取得统计数

System.out.println("sum="+ list.stream().mapToInt(UserBean::getUserId).sum());
System.out.println("min="+ list.stream().mapToInt(UserBean::getUserId).min().getAsInt());
System.out.println("average="+ list.stream().mapToInt(UserBean::getUserId).average().getAsDouble());
System.out.println("count="+ list.stream().mapToInt(UserBean::getUserId).count());
System.out.println("max="+ list.stream().mapToInt(UserBean::getUserId).max().getAsInt());

匹配

boolean anyMatch = list.stream().anyMatch(userBean -> userBean.getUserName().indexOf("a") > 0);
if(anyMatch) System.out.println("有任意匹配到a");
//类似的还有全匹配、全部匹配

评论系统未开启,无法评论!