前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java8 Stream流操作学习总结

Java8 Stream流操作学习总结

作者头像
用户5224393
发布2019-08-13 15:56:45
7300
发布2019-08-13 15:56:45
举报
文章被收录于专栏:Java研发军团Java研发军团
代码语言:javascript
复制
作者:一杯甜酒 原文:https://blog.csdn.net/u012562943/article/details/81775926

引言

传统的数据处理都是用循环来解决,而不是像搜索数据库那样有具体的搜索语句,而Java8的Stream提供了很好的方案,往往一行就搞定了,而且Stream还可以链式操作,一行代码实现多个循环的功能,代码风格十分像nosql数据库。

但是在实际应用中发现一个巨大的问题,就是执行耗时特别长,时间开销是传统方法的几百倍,这是一个巨大的问题。

Java8可以像操作数据库一样操作内存,而且在Stream操作中对内存的开销十分友善,操作方式十分灵活,减少了IO的支出。

下面是一个小例子代码:

代码语言:javascript
复制
package com.zhy.demo.javase.java8.stream;
 
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
 
/**
 * @ClassName User
 * @Description (User类用来代表用户,里面有姓名年龄密码等常用字段)
 * @author ZHY
 * @date 2018年8月15日 下午11:15:26
 * @Copyright © 2018【www.zhy.com Inc. All rights reserved.】
 */
public class User implements Comparable<User> {
  /**
   * 年龄
   */
  private int age;
  /**
   * 姓名
   */
  private String name;
  /**
   * 密码
   */
  private String password;
 
  /**
   * 性别,0未知,1男,2女
   */
  private short gendar;
 
  /**
   * 是否已婚
   */
  private boolean hasMarried;
 
  public User() {
    super();
  }
 
  public User(int age, String name, String password, short gendar, boolean hasMarried) {
    super();
    this.age = age;
    this.name = name;
    this.password = password;
    this.gendar = gendar;
    this.hasMarried = hasMarried;
  }
 
  public int getAge() {
    return age;
  }
 
  public void setAge(int age) {
    this.age = age;
  }
 
  public String getName() {
    return name;
  }
 
  public void setName(String name) {
    this.name = name;
  }
 
  public String getPassword() {
    return password;
  }
 
  public void setPassword(String password) {
    this.password = password;
  }
 
  public short getGendar() {
    return gendar;
  }
 
  public void setGendar(short gendar) {
    this.gendar = gendar;
  }
 
  public boolean isHasMarried() {
    return hasMarried;
  }
 
  public void setHasMarried(boolean hasMarried) {
    this.hasMarried = hasMarried;
  }
 
  @Override
  public String toString() {
    return "User [age=" + age + ", name=" + name + ", password=" + password + ", gendar=" + gendar + ", hasMarried="
        + hasMarried + "]";
  }
 
  /**
   * (重写对象是否重复方法)
   * 
   * @see java.lang.Object#equals(java.lang.Object)
   */
  @Override
  public boolean equals(Object obj) {
 
    if (!(obj instanceof User)) {
      return false;
    }
    User u = (User) obj;
    if (age != u.age || gendar != u.gendar || hasMarried != u.hasMarried || !name.equals(u.name)
        || !password.equals(u.getPassword())) {
      return false;
    }
    return true;
  }
 
  /**
   * (Stream去重有一个先决条件,就是要去重的对象必须实现comparable接口,不能使用比较器)
   * 
   * @see java.lang.Comparable#compareTo(java.lang.Object)
   */
  @Override
  public int compareTo(User o2) {
 
    // 首先比较年龄大小,因为年龄的区分度比较高
    User o1 = this;
    if (o1.age > o2.age) {
      return 1;
    }
    if (o1.age < o2.age) {
      return -1;
    }
    // 如果年龄相同就比较性别,女的排在前面
    if (o1.gendar > o2.gendar) {
      return 1;
    }
    if (o1.gendar < o2.gendar) {
      return -1;
    }
    // 如果性别也一样就比较是否已婚
    if (o1.hasMarried == true && o2.hasMarried == false) {
      // 结婚的排在前面
      return 1;
    }
    if (o1.hasMarried == false && o2.hasMarried == true) {
      // 结婚的排在前面
      return 1;
    }
    // 最后比较姓名,因为字符串比较耗时较长
    if (o1.name.hashCode() > o2.name.hashCode()) {
      return 1;
    }
    if (o1.name.hashCode() < o2.name.hashCode()) {
      return -1;
    }
    return 0;
  }
 
  public List<User> createUserDatas() {
 
    ArrayList<User> userList = new ArrayList<>();
    userList.add(new User(22, "王旭", "123456", (short) 1, true));
    userList.add(new User(22, "王旭", "123456", (short) 1, true));
    userList.add(new User(22, "王旭", "123456", (short) 1, true));
    userList.add(new User(21, "孙萍", "a123456", (short) 2, false));
    userList.add(new User(23, "步传宇", "b123456", (short) 1, false));
    userList.add(new User(18, "蔡明浩", "c123456", (short) 1, true));
    userList.add(new User(17, "郭林杰", "d123456", (short) 1, false));
    userList.add(new User(5, "韩凯", "e123456", (short) 1, true));
    userList.add(new User(22, "韩天琪", "f123456", (short) 2, false));
    userList.add(new User(21, "郝玮", "g123456", (short) 2, false));
    userList.add(new User(19, "胡亚强", "h123456", (short) 1, false));
    userList.add(new User(14, "季恺", "i123456", (short) 1, false));
    userList.add(new User(17, "荆帅", "j123456", (short) 1, true));
    userList.add(new User(16, "姜有琪", "k123456", (short) 1, false));
    return userList;
  }
 
  /**
   * 按照年龄大小进行排序,设计一个Comparator
   * 
   * @return
   */
  public Comparator<User> getAgeComparator() {
 
    return new Comparator<User>() {
      @Override
      public int compare(User o1, User o2) {
        if (o1.age > o2.age)
          return 1;
        if (o1.age < o2.age)
          return -1;
        return 0;
      }
    };
  }
 
  public Comparator<User> getEqualComparator() {
 
    return new Comparator<User>() {
      @Override
      public int compare(User o1, User o2) {
        // 首先比较年龄大小,因为年龄的区分度比较高
        if (o1.age > o2.age) {
          return 1;
        }
        if (o1.age < o2.age) {
          return -1;
        }
        // 如果年龄相同就比较性别,女的排在前面
        if (o1.gendar > o2.gendar) {
          return 1;
        }
        if (o1.gendar < o2.gendar) {
          return -1;
        }
        // 如果性别也一样就比较是否已婚
        if (o1.hasMarried == true && o2.hasMarried == false) {
          // 结婚的排在前面
          return 1;
        }
        if (o1.hasMarried == false && o2.hasMarried == true) {
          // 结婚的排在前面
          return 1;
        }
        // 最后比较姓名,因为字符串比较耗时较长
        if (o1.name.hashCode() > o2.name.hashCode()) {
          return 1;
        }
        if (o1.name.hashCode() < o2.name.hashCode()) {
          return -1;
        }
        return 0;
      }
    };
  }
 
}
代码语言:javascript
复制
package com.zhy.demo.javase.java8.stream;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
 
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
 
import com.alibaba.fastjson.JSON;
 
/**
 * @ClassName StreamStudy
 * @Description (Java8 Stream操作总结)
 * @author ZHY
 * @date 2018年8月15日 下午11:17:27
 * @Copyright © 2018【www.zhy.com Inc. All rights reserved.】
 */
public class StreamTest {
 
  private static final Logger LOGGER = LoggerFactory.getLogger(StreamTest.class);
 
  private static User user = new User();
 
  /**
   * 对用户按年龄进行排序
   */
  @Test
  public void testSort1() {
 
    // 传统方式排序
    LOGGER.info("===============传统方式排序===============");
    List<User> userList1 = user.createUserDatas();
    long time1 = System.currentTimeMillis();
    Collections.sort(userList1, user.getAgeComparator());
    LOGGER.info("传统方式排序耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
    userList1.stream().forEach(user -> {
      LOGGER.info(user.toString());
    });
    // Java8的方式排序
    LOGGER.info("==============Java8的方式排序=============");
    List<User> userList2 = user.createUserDatas();
    long time2 = System.currentTimeMillis();
    List<User> sortedUsers = userList2.stream().sorted(user.getAgeComparator()).collect(Collectors.toList());
    LOGGER.info("Java8的方式排序耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
    sortedUsers.stream().forEach(user -> {
      LOGGER.info(user.toString());
    });
  }
 
  /**
   * 选出年龄最小的三个人
   */
  @Test
  public void testSort2() {
 
    // 传统方式排序
    LOGGER.info("===============传统方式排序===============");
    List<User> userList1 = user.createUserDatas();
    long time1 = System.currentTimeMillis();
    Collections.sort(userList1, user.getAgeComparator());
    // 切割出0,1,2这三个子元素
    List<User> userListTopThree1 = userList1.subList(0, 3);
    LOGGER.info("传统方式排序耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
    userListTopThree1.stream().forEach(user -> {
      LOGGER.info(user.toString());
    });
    // Java8的方式排序
    LOGGER.info("==============Java8的方式排序=============");
    List<User> userList2 = user.createUserDatas();
    long time2 = System.currentTimeMillis();
    List<User> userListTopThree2 = userList2.stream().sorted(user.getAgeComparator()).limit(3)
        .collect(Collectors.toList());
    LOGGER.info("Java8的方式排序耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
    userListTopThree2.stream().forEach(user -> {
      LOGGER.info(user.toString());
    });
  }
 
  /**
   * 去除重复数据
   */
  @Test
  public void testDisdinct() {
 
    // 传统方式去重
    LOGGER.info("===============传统方式去重===============");
    List<User> userList1 = user.createUserDatas();
    long time1 = System.currentTimeMillis();
    int length = userList1.size();
    for (int i = 1; i < length; i++) {
      if (userList1.get(i).equals(userList1.get(i - 1))) {
        userList1.remove(i);
        i--;
        length--;
      }
    }
    LOGGER.info("传统方式去重耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
    userList1.stream().forEach(user -> {
      LOGGER.info(user.toString());
    });
    // Java8的方式去重
    LOGGER.info("==============Java8的方式去重=============");
    List<User> userList2 = user.createUserDatas();
    long time2 = System.currentTimeMillis();
    List<User> distinctUserList = userList2.stream().sorted().distinct().collect(Collectors.toList());
    LOGGER.info("Java8的方式去重耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
    distinctUserList.stream().forEach(user -> {
      LOGGER.info(user.toString());
    });
  }
 
  /**
   * 按条件筛选
   */
  @Test
  public void testFilter() {
 
    // 传统方式按条件筛选
    LOGGER.info("===============传统方式按条件筛选===============");
    List<User> userList1 = user.createUserDatas();
    long time1 = System.currentTimeMillis();
    ArrayList<User> result1 = new ArrayList<>();
    for (User user : userList1) {
      if (user.getName().startsWith("韩"))
        result1.add(user);
    }
    LOGGER.info("传统方式按条件筛选耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
    result1.stream().forEach(user -> {
      LOGGER.info(user.toString());
    });
    // Java8的方式按条件筛选
    LOGGER.info("==============Java8的方式按条件筛选=============");
    List<User> userList2 = user.createUserDatas();
    long time2 = System.currentTimeMillis();
    List<User> result2 = userList2.stream().filter(user -> user.getName().startsWith("韩"))
        .collect(Collectors.toList());
    LOGGER.info("Java8的方式按条件筛选耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
    result2.stream().forEach(user -> {
      LOGGER.info(user.toString());
    });
    List<User> result3 = userList2.stream().filter(user -> user.getName().startsWith("韩") && user.getGendar() == 2)
        .collect(Collectors.toList());
    List<User> result4 = userList2.stream().filter(user -> user.getName().startsWith("韩"))
        .filter(user -> user.getGendar() == 2).collect(Collectors.toList());
    List<User> result5 = userList2.stream().filter(user -> user.getGendar() == 2)
        .filter(user -> user.getName().startsWith("韩")).collect(Collectors.toList());
    LOGGER.info("result3 ==> {}", JSON.toJSONString(result3, true));
    LOGGER.info("result4 ==> {}", JSON.toJSONString(result4, true));
    LOGGER.info("result5 ==> {}", JSON.toJSONString(result5, true));
  }
 
  /**
   * 只列出所有人的名字和婚姻状况
   */
  @Test
  public void testMap() {
 
    // 传统方式
    LOGGER.info("===============传统方式===============");
    List<User> userList1 = user.createUserDatas();
    long time1 = System.currentTimeMillis();
    ArrayList<String> result1 = new ArrayList<String>();
    for (User user : userList1) {
      result1.add(user.getName() + ":".concat(user.isHasMarried() ? "已婚" : "未婚"));
    }
    LOGGER.info("传统方式耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
    result1.stream().forEach(user -> {
      LOGGER.info(user.toString());
    });
    // Java8的方式
    LOGGER.info("==============Java8的方式序=============");
    List<User> userList2 = user.createUserDatas();
    long time2 = System.currentTimeMillis();
    List<String> result2 = userList2.stream()
        .map(user -> user.getName() + ":".concat(user.isHasMarried() ? "已婚" : "未婚"))
        .collect(Collectors.toList());
    LOGGER.info("Java8的方式耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
    result2.stream().forEach(user -> {
      LOGGER.info(user.toString());
    });
  }
 
  /**
   * 判断当前数组是否包含某些特定元素
   */
  @Test
  public void testAnyMatch() {
 
    // 传统方式
    LOGGER.info("===============传统方式===============");
    List<User> userList1 = user.createUserDatas();
    long time1 = System.currentTimeMillis();
    boolean isChild1 = false;
    for (User user : userList1) {
      if (user.getAge() < 18) {
        isChild1 = true;
        break;
      }
    }
    LOGGER.info("传统方式耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
    LOGGER.info("isChild1 ==> {}", isChild1);
    // Java8的方式
    LOGGER.info("==============Java8的方式序=============");
    List<User> userList2 = user.createUserDatas();
    long time2 = System.currentTimeMillis();
    boolean isChild2 = userList2.stream().anyMatch(user -> user.getAge() < 18);
    LOGGER.info("Java8的方式耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
    LOGGER.info("isChild2 ==> {}", isChild2);
  }
 
  /**
   * 确认所有元素均满足某一条件
   */
  @Test
  public void testAllMatch() {
 
    // 传统方式
    LOGGER.info("===============传统方式===============");
    List<User> userList1 = user.createUserDatas();
    long time1 = System.currentTimeMillis();
    boolean allMarried1 = true;
    for (User user : userList1) {
      if (!user.isHasMarried()) {
        allMarried1 = false;
        break;
      }
    }
    LOGGER.info("传统方式耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
    LOGGER.info("allMarried1 ==> {}", allMarried1);
    // Java8的方式
    LOGGER.info("==============Java8的方式序=============");
    List<User> userList2 = user.createUserDatas();
    long time2 = System.currentTimeMillis();
    boolean allMarried2 = userList2.stream().allMatch(user -> user.isHasMarried());
    LOGGER.info("Java8的方式耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
    LOGGER.info("allMarried2 ==> {}", allMarried2);
  }
 
  /**
   * 求和求平均值
   */
  @Test
  public void testSum() {
 
    // 传统方式
    LOGGER.info("===============传统方式===============");
    List<User> userList1 = user.createUserDatas();
    long time1 = System.currentTimeMillis();
    int sum1 = 0;
    for (User user : userList1) {
      sum1 += user.getAge();
    }
    LOGGER.info("传统方式耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
    LOGGER.info("sum ==> {}", sum1);
    // Java8的方式
    LOGGER.info("==============Java8的方式序=============");
    List<User> userList2 = user.createUserDatas();
    long time2 = System.currentTimeMillis();
    int sum2 = userList2.stream().mapToInt(user -> user.getAge()).sum();
    LOGGER.info("Java8的方式耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
    LOGGER.info("sum2 ==> {}", sum2);
  }
 
  /**
   * 分组
   */
  @Test
  public void testGroupingBy() {
 
    // 传统方式
    LOGGER.info("===============传统方式===============");
    List<User> userList1 = user.createUserDatas();
    long time1 = System.currentTimeMillis();
    Map<Integer, List<User>> group1 = new HashMap<>();
    for (User user : userList1) {
      List<User> list = group1.get(user.getAge());
      if (list == null) {
        list = new ArrayList<User>();
        group1.put(user.getAge(), list);
      }
      list.add(user);
    }
    LOGGER.info("传统方式耗时 ==> {} (ms)", System.currentTimeMillis() - time1);
    LOGGER.info("group1 ==> {}", JSON.toJSONString(group1), true);
    // Java8的方式
    LOGGER.info("==============Java8的方式序=============");
    List<User> userList2 = user.createUserDatas();
    long time2 = System.currentTimeMillis();
    Map<Integer, List<User>> group2 = userList2.stream().collect(Collectors.groupingBy(t -> t.getAge()));
    // 如果想按是否结婚分组,也就是key变成bool,那就应该这么写
    // Map<Boolean,List<User>> group =
    // users.stream().collect(Collectors.partitioningBy(t->t.hasMarried));
    LOGGER.info("Java8的方式耗时 ==> {} (ms)", System.currentTimeMillis() - time2);
    LOGGER.info("group2 ==> {}", JSON.toJSONString(group2), true);
  }
 
  /**
   * 链式操作
   */
  @Test
  public void testLinkOperation() {
 
    LOGGER.info("==============Java8链式操作=============");
    List<User> userList = user.createUserDatas();
    long time = System.currentTimeMillis();
    userList.stream().filter(t -> t.getGendar() == 2).map(t -> t.getName()).forEach(System.out::println);
    LOGGER.info("Java8链式操作耗时 ==> {} (ms)", System.currentTimeMillis() - time);
  }
 
}

大家最好把上面代码复制到便一起上试试!!!

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-11-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java研发军团 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言
  • 下面是一个小例子代码:
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档