栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java8 新特性之 Stream 常用方法总结

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java8 新特性之 Stream 常用方法总结

Stream

当我们在需要对集合中的元素进行操作的时候,除了必需的添加,删除,获取外,最典型的就是遍历数组了

public static void main(String[] args) {
  List list = Arrays.asList("AAA","ABB","As","CC","DD");

  // 获取所有以 A 开头的数据
  List list1 = new ArrayList<>();
  for (String s : list) {
    if(s.startsWith("A")){
      list1.add(s);
    }
  }

  List list2 = new ArrayList<>();
  // 获取长度为 3 的数据
  for (String s : list1) {
    if (s.length() == 3) {
      list2.add(s);
    }
  }
  for (String s : list2) {
    System.out.println(s);
  }
}

以上代码可以看出有很多的循环,只要有了不同的需求,就需要进行一遍循环,是很繁琐的,因此,通过 JDK8 新特性的stream流可以解决这个问题。

Stream 更加优雅的代码解决方案

public static void main(String[] args) {
  List list = Arrays.asList("AAA","ABB","As","CC","DD");

  // 获取所有以 A 开头的数据
  // 获取长度为 3 的数据
  list.stream()
          .filter(s -> s.startsWith("A"))
          .filter(s -> s.length() == 3)
          .forEach(System.out::println);
}

以上代码含义:获取流,过滤“A”,过滤长度,逐一打印。代码相比于上面的案例更加简介直观

1. Stream流式思想概述

Stream流式思想类似于工厂车间的“生产流水线”,Stream流不是一种数据结构,不保存数据,而是对数据进行加工处理。Stream可以看作是流水线上的一个工序。在流水线上,通过多个工序让一个原材料加工成一个商品。

Stream API 可以让我们快速完成许多复制的操作,如筛选,切片,映射,查找,去重复,统计,匹配和归约

2. Stream流的获取方式 2.1 根据Collection获取

首先, java.util.Collection 接口中加入了 defatult 方法 Stream,也就是说 Collection 接口下的所有的实现都可以通过 stream 方法来获取 Stream 流。

public static void main(String[] args) {
  List list = Arrays.asList("AAA","ABB","As","CC","DD");
  list.stream();

  Set set = new HashSet<>();
  set.stream();

  Vector vector = new Vector();
  vector.stream();
}

对于集合 Map 接口没有实现 Collection 接口,那么,我们可以根据 Map 获取对应的 key 和 value 的集合

2.2 通过 Stream 的 of 方法

在实际开发中我们不可避免的还是会操作到数组中的数据,由于数组对象不可能添加默认方法,所有Stream接口中提供了静态方法 of

public static void main(String[] args) {
  Stream a1 = Stream.of("a1", "a2", "a3");
  String[] arr1 = {"aa","bb","cc"};
  Stream arr11 = Stream.of(arr1);
  Integer[] arr2 = {1,2,3,4};
  Stream arr21 = Stream.of(arr2);
  arr21.forEach(System.out::println);

  // 注意:基本数据类型的数组是不会将其中的元素一个一个给打印出来的
  int[] arr3 = {1,2,3,4};
  Stream.of(arr3).forEach(System.out::println);
}
3. Stream 常用方法 3.1 forEach —— 终结方法

forEach 用来遍历流中的数据的

void forEach(Consumer action);

该方法接受一个 Consumer 接口,会将每一个流元素交给函数处理

public static void main(String[] args) {
  Stream.of("aa","bb","cc","dd").forEach(System.out::println);
}
3.2 count —— 终结方法

Stream流中的 count 方法用来统计其中的元素个数的

long count();

该方法返回一个 long 值,代表元素的个数

long count = Stream.of("aa", "bb", "cc", "dd").count();
System.out.println(count);
3.3 filter

filter 方法的作用是用来过滤数据数据的。返回符合条件的数据。

可以通过filter方法将一个流转换成另一个子集流

Stream filter(Predicate predicate);

该接口接收一个 Predicate 函数式接口参数作为筛选条件

Stream.of("a1","a2","a3","s","sa","d","f","cc","xx")
        .filter(s -> s.contains("a"))
        .forEach(System.out::println);

输出:

a1
a2
a3
sa

3.4 limit

limit 方法可以对流进行截取处理,只取前 n 个数据

Stream limit(long maxSize);

参数是一个 long 类型的数值,如果集合当前长度大于参数就进行截取,否则不进行操作

Stream.of("a1","a2","a3","s","sa","d","f","cc","xx")
        .limit(3)
        .forEach(System.out::println);

输出

a1
a2
a3
3.5 skip

如果希望跳过前面几个元素,可以使用 skip 方法获取一个截取之后的新流

Stream skip(long n);

操作:

Stream.of("a1","a2","a3","s","sa","d","f","cc","xx")
        .skip(3)
        .forEach(System.out::println);

输出:

s
sa
d
f
cc
xx
3.6 map

如果我们需要将流中的元素映射到另一个流中,可以使用 map 方法

 Stream map(Function mapper);

该接口需要一个Function函数式接口参数,可以将当前流中的 T 类型数据转换成另一种 R 类型的数据

Stream.of("1","2","3","4","5","6","7")
        .map(Integer::parseInt)
        .forEach(System.out::println);
3.7 sorted

如果需要将数据排序,可以使用 sorted 这个方法

Stream sorted();

在使用的时候可以根据自然规则排序,也可以通过比较来指定对应的排序规则

Stream.of("1","3","2","0","9","4","7")
        .map(Integer::parseInt)
        .sorted() // 根据数据日然顺序排序
        .sorted((o1,o2) -> 02 - o1)
        .forEach(System.out::println);
3.8 distinct

如果要去掉重复的数据,可以使用该方法

Stream distinct();

使用

Stream.of("1","3","2","2","7","4","7")
        .map(Integer::parseInt)
        .sorted() // 根据数据日然顺序排序
        .sorted((o1,o2) -> 02 - o1)
        .distinct()
        .forEach(System.out::println);

Stream.of(
        new Person("张三",18),
        new Person("李四",22),
        new Person("张三",18)
).distinct()
        .forEach(System.out::println);

Stream 流中的 distinct 基本数据类型是可以直接去重的,但是自定义数据类型,我们需要重写 hashCode 和 equals 方法来进行去重

3.9 match anyMatch、allMatch、noneMatch

anyMatch 表示判断的条件里,任意一个元素成功,返回 true

allMatch 表示判断里的元素,所有的都是,返回 true

noneMatch 跟 allMatch 相反,判断条件里的元素,所有的都不是,返回 true

List strs = Arrays.asList("a", "a", "a", "a", "b");
boolean aa = strs.stream().anyMatch(str -> str.equals("a"));
boolean bb = strs.stream().allMatch(str -> str.equals("a"));
boolean cc = strs.stream().noneMatch(str -> str.equals("a"));
long count = strs.stream().filter(str -> str.equals("a")).count();
System.out.println(aa);// TRUE
System.out.println(bb);// FALSE
System.out.println(cc);// FALSE
System.out.println(count);// 4
3.10 find findFirst、findAny

findFirst:返回列表中的第一个元素。

findAny:返回的元素是不确定的,对于同一个列表多次调用 findAny() 有可能会返回不同的值。使用 findAny() 是为了更高效的性能。如果是数据较少,串行的情况下,一般会返回第一个结果,如果是并行的情况,那就不能确保是第一个。

List lst1 = Arrays.asList("Jhonny", "David", "Jack", "Duke", "Jill","Dany","Julia","Jenish","Divya");
List lst2 = Arrays.asList("Jhonny", "David", "Jack", "Duke", "Jill","Dany","Julia","Jenish","Divya");
 
Optional findFirst = lst1.parallelStream().filter(s -> s.startsWith("D")).findFirst();
Optional fidnAny = lst2.parallelStream().filter(s -> s.startsWith("J")).findAny();
 
System.out.println(findFirst.get()); //总是打印出David
System.out.println(fidnAny.get()); //会随机地打印出Jack/Jill/Julia
3.11 max 和 min max
Optional max = Stream.of(
        new Person("aa", 77),
        new Person("bb", 66),
        new Person("cc", 55),
        new Person("dd", 44),
        new Person("eef", 33),
        new Person("ff", 22)
).max(Comparator.comparingInt(Person::getAge));
System.out.println(max);
max.ifPresent(s -> System.out.println(s.getAge()));

// 结果
Optional[Person{name='aa', age=77}]
77
min
Optional max = Stream.of(
        new Person("aa", 77),
        new Person("bb", 66),
        new Person("cc", 55),
        new Person("dd", 44),
        new Person("eef", 33),
        new Person("ff", 22)
).min(Comparator.comparingInt(Person::getAge));
System.out.println(max);
max.ifPresent(s -> System.out.println(s.getAge()));

// 结果
Optional[Person{name='ff', age=22}]
22
3.12 reduce 方法

如果需要将所有数据归纳得到又给数据,可以使用 reduce 方法

T reduce(T identity, BinaryOperator)

使用:

public static void main(String[] args) {
  Integer sum = Stream.of(3,4,5,9)
          // identity 默认值
          // 第一次的时候会将默认值赋值给 x
          // 之后每次会将 上一次的操作结果赋值给x  y就是每次从数据中获取的元素
          .reduce(0, (x, y) -> {
            return x + y;
          });
  System.out.println(sum);

  // 获取最大值
  Integer max = Stream.of(4,5,3,9)
          .reduce(0, (x, y) -> {
            return x > y? x : y;
          });
  System.out.println(max);
}
3.13 map 和 reduce 的组合
Integer sum = Stream.of(3,4,5,9)
        // identity 默认值
        // 第一次的时候会将默认值赋值给 x
        // 之后每次会将 上一次的操作结果赋值给x  y就是每次从数据中获取的元素
        .reduce(0, (x, y) -> x + y);
System.out.println(sum);

// 获取最大值
Integer max = Stream.of(4,5,3,9)
        .reduce(0, (x, y) -> x > y? x : y);
System.out.println(max);


Integer sumAge = Stream.of(
        new Person("aa", 22),
        new Person("bb", 32),
        new Person("cc", 12),
        new Person("dd", 56),
        new Person("ee", 43)
).map(Person::getAge)
        .reduce(0, Integer::sum);
System.out.println(sumAge);

// 求年龄的最大值
Integer maxAge = Stream.of(
        new Person("aa", 22),
        new Person("bb", 32),
        new Person("cc", 12),
        new Person("dd", 56),
        new Person("ee", 43)
).map(Person::getAge)
        .reduce(0, Math::max);
System.out.println(maxAge);

Integer count = Stream.of("a", "b", "c", "d").map(ch -> "a".equals(ch) ? 1 : 0)
        .reduce(0, Integer::sum);
System.out.println(count);
3.14 mapToInt

如果需要将 Stream 中的 Integer 类型转换成 int 类型,可以使用 mapToInt 方法来实现

使用

// Integer 占用的内存比 int 多很多,在 Stream 流操作中会自动装修和拆箱操作
Integer arr[] = {1,2,3,5,6,8};
Stream.of(arr)
        .filter(i -> i > 0)
        .forEach(System.out::println);
System.out.println("----------------");
// 为了提高程序代码的效率,我们可以先将流中的 Integer 数据转换为 int 数据,然后再操作
IntStream intStream = Stream.of(arr)
        .mapToInt(Integer::intValue);
intStream.filter(i -> i > 3)
        .forEach(System.out::println);
3.15 concat

如果有两个流希望合并成一个流,那么可以使用 Stream 接口的静态方法 concat

使用:

Stream stream1 = Stream.of("a","b","c");
Stream stream2 = Stream.of("x","y","z");
// 通过 concat 方法将两个流合并为一个新的流
Stream.concat(stream1, stream2).forEach(System.out::println);
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/325634.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号