阅读 171

Java系列——Stream流操作总结

自从 Java8 引入流以来,总能在 code review 的时候看见别人写出一手优雅简洁的代码,自己却总是在写代码的忘记或不知道什么时候该用 stream 风格来改造代码。本文也是用边总结边扩充的方式将一些用法收集出来,一方面供自己后续查看,一方面与读者分享。

流是什么

流是一种元素序列,它不存储元素,也不修改原始源。

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象,让程序员写出高效率、干净、简洁的代码。

元素流在管道中经过中间操作的处理,最后由最终操作得到前面处理的结果。

stream.png

怎么产生流

Stream.of(T... values) 和 Stream.of(T t)

Stream.of("张三","李四","王五")
复制代码

Stream.iterate(T seed, UnaryOperator f)

// 一般都会加上 limit 操作,将无限流变成有限流
Stream.iterate(0, n -> n + 1).limit(10)
复制代码

Stream.generate(Supplier s)

Stream.generate(Math::random).limit(10)
复制代码

Arrays.stream(T[] array)

// String[] names = {"张三","李四","王五"};
Arrays.stream(names)
复制代码

Collection.stream()

// List<String> names = Arrays.asList("张三","李四","王五");
names.stream()
复制代码

借助流可以做哪些事情

求和

// List<Integer> numberList = Arrays.asList(1,2,3);
int sum = numberList.stream().reduce((x,y) -> x + y).orElse(0);
复制代码

筛选数据

// List<String> alphaList  = Arrays.asList("a","ab","abc","acb");

alphaList.stream().filter(e -> e.contain("a")).collect(toList())
复制代码

拼接字符串

// String[] names = {"张三","李四","王五"};

// 方法一
names.reduce("",String::concat)

// 方法二
names.collect(() -> new StringBuilder(),
        (sb, str) -> sb.append(str),
        (sb1,sb2) -> sb1.append(sb2))
    .toString();
    
// 方法三
names.collect(Collectors.joining());
复制代码

将 POJO 集合转成映射

/**
public class User {
    
    private Long id;
    private String name;
    
    // 省略 getter、setter 和构造函数等
}
*/

// 构建属性与属性的映射
Map<Long,String> idNameMap = users.stream().collect(Collectors.toMap(User::getId,User::getName));

// 构建属性与实例的映射
Map<Long,User> userMap = users.stream().collect(Collectors.toMap(User::getId, u -> u));
// 或者 userMap = users.stream().collect(Collectors.toMap(User::getId, Function.identity()));
复制代码

对 POJO 集合进行分组

/**
public class User {
    
    private Long id;
    private String name;
    private Integer age;
    private Boolean isLeader;
    
    // 省略 getter、setter 和构造函数等
}
*/

// 将 users 分为 leader 和 employee
Map<Boolean,List<User>> isLeaderMap = users.stream().collect(Collectors.partitioningBy(User::getIsLeader));

// 将 users 按年龄分组
Map<Integer,List<User>> ageMap = users.stream().collect(Collectors.groupingBy(User::getAge));
复制代码

对数据进行排序

// List<String> alphaList  = Arrays.asList("a","ab","abc","acb");

// 根据长度排序
alphaList.stream().sorted((s1,s2) -> s1.length() - s2.length()).collect(toList());
alphaList.stream().sorted(Comparator.comparingInt(String::length)).collect(toList());

// 先根据长度排序,长度相同再按字母顺序排序
alphaList.stream().sorted(comparing(String::length).thenComparing(naturalOrder())).collect(toList());
复制代码

确定集合中是否存在符合某种规则的数据存在

// List<String> alphaList  = Arrays.asList("a","ab","abc","acb");

// 是否存在包含字母 a 的字符串
alphaList.stream().anyMatch(e -> e.contains("a"));

// 是否所有字符串都包含字母 a 
alphaList.stream().allMatch(e -> e.contains("a"));

// 是否所有字符串都不包含字母 a
alphaList.stream().noneMatch(e -> e.contains("a"));
复制代码

其他

当然还有很多的事情可以做,但是作者用的较多的都列出来了,其他的过于简单的或者不常用的就省略了。

如果觉得本文对您有帮助,请点赞分享或关注起来,如果有兴趣也可以浏览作者的其他文章。
如果觉得本文浪费了您的时间,希望评论区能留下您的宝贵意见。
如果有疑问也请留言,作者愿花时间和精力去找寻答案,一起探讨。

文章分类
后端
文章标签