Stream流

Stream流把真正的函数式编程风格引入到Java中

Java中的Stream流是用于对集合(Collection)对象进行一系列操作的工具。它提供了一种流式操作的方式,可以进行过滤、映射、排序、聚合等各种操作,类似于UNIX中的管道操作,能够简洁高效地处理数据。

Stream流的主要作用包括:

  1. 简化集合操作: 使用Stream可以通过一系列的中间操作来对集合进行处理,而不需要繁琐地使用循环等传统方式。这样可以使代码更加简洁易读。
  2. 延迟执行: Stream提供了延迟执行的特性,只有在终端操作(如forEach、collect等)被调用时,才会触发中间操作的执行。这种延迟执行可以提高性能,避免不必要的计算。
  3. 并行处理: Stream提供了并行处理的能力,可以很容易地将串行操作转换为并行操作,充分利用多核处理器的性能优势,加快处理速度。
  4. 支持函数式编程: Stream提供了丰富的函数式编程特性,如map、filter、reduce等操作,使得在处理集合时可以更加灵活地使用函数式编程的思想。
    总之,Java中的Stream流提供了一种更加便利和高效的方式来处理集合数据,使得代码更加简洁、易读,并且能够充分发挥现代计算机的性能优势。

Stream流的生成方式

Stream流的使用
生成流
通过数据源(集合,数组等)生成流
list.stream()

中间操作
一个流后面可以跟随零个或多个中间操作,其目的主要是打开流,做出某种程度的数据过滤/映射,然后返回一个新的流交给下一个操作使用
filter()

终结操作
一个流只能有一个终结操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作
forEach()

(1)Stream流的常见生成方式

Collection体系的集合可以使用默认方法stream()生成流
    default Stream< E > stream()
Map体系的集合间接的生成流
数组可以通过Stream接口的静态方法**of(T…values)**生成流

Collection 体系的集合

CoLLection体系的集合可以使用默认方法stream()生成流

1
2
3
4
5
List<String> list = new ArrayList<String>();
Stream<String> listStream = list.stream();

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

Map 体系的集合

Map体系的集合间接的生成流

1
2
3
4
Map<String,Integer> map = new HashMap<String,Integer>();
Stream<String> keyStream = map.keySet().stream();
Stream<Integer> valueStream = map.values().stream();
Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();

数组

数组可以通过 stream 接口的静态方法 of(T… values) 生成流

1
2
3
4
5
String[] strArray = {"hello","world","java"};
Stream<String> strArrayStream = Stream.of(strArray);

Stream<String> strArrayStream2 = Stream.of("hello","world","java");
Stream<Integer> intStream = Stream.of(10,2,30);

(2)Stream流的常见中间操作方法

filter

Stream< T > filter(Predicate predicate): 用于对流中的数据进行过滤
Predicate接口中的方法:boolean test(T t):对给定的参数进行判断,返回一个布尔值

1
2
//需求:把List集合中以张开头的,长度为3的元素在控制台输出
list.stream().filter(s -> s.startswith("张")).filter(s -> s.length() == 3).forEach(System,out::println);

limit skip

Stream< T >limit(long maxSize): 返回此流中的元素组成的流,截取前指定参数个数的数据(取前几个)
Stream< T >skip(long n):跳过指定参数个数的数据,返回由该流的剩余元素组成的流(跳过前几个,返回剩下的)

1
2
//需求:跳过2个元素,把剩下的元素中前2个在控制台输出
list.stream().skip(2).limit(2).forEach(System.out::println);

concat distinct

static< T > Stream< T > concat(Stream a,Stream b): 合并a和b两个流为一个流(注意这个是静态方法)
Stream< T > distinct(): 返回由该流的不同元素(根据Object.equals(Object)) 组成的流

1
2
3
4
5
6
//需求1:取前4个数据组成一个流
Stream<String> s1 = list.stream().limit(4);
//需求2:跳过2个数据组成一个流
Stream<String> s2 = list.stream().skip(2);
//需求3:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复
Stream.concat(s1,s2).distinct().forEach(System.out::printIn); //合并&&不重复

sorted

Stream< T > sorted():返回由此流的元素组成的流,根据自然顺序排序
Stream< T > sorted(Comparator comparator): 返回由该流的元素组成的流,根据提供的Comparator比较器进行排序

1
2
3
4
5
6
7
8
9
10
//需求1:按照字母顺序把数据在控制台输出(自然排序)
List.stream().sorted().forEach(System.out::println);

//需求2:按照字符串长度把数据在控制台输出(比较器排序)
//list.stream().sorted((s1, s2) -> s1.length() - s2.length()).forEach(System.out::println);

list.stream().sorted((s1,s2) -> {
int num = s1.length() - s2.length();
int num2 = num == 0 ? s1.compareTo(s2) : num;
}).forEach(System.out::println);

map mapToInt

< R > Stream < R > map(Function mapper):返回由给定函数应用于此流的元素的结果组成的流
Function接口中的方法 —> R apply(T t)

IntStream mapTolnt(ToIntFunction mapper):返回一个 IntStream 其中包含将给定函数应用于此流的元素的结果
IntStream:表示原始int流

ToIntFunction 接口中的方法 —> int applyAsInt(T value)
(mapToInt()方法可以将 Stream 流转化为 IntStream ,就可以接着使用 IntStream 中特殊的方法)

使用案例:
将一个 Set 集合转换为数组:
int[] array = res.stream().mapToInt(Integer::intValue).toArray();

IntStream

IntStream 接口中的方法:

Modifier and Type 方法 描述
int sum() 返回此流中元素的总和
int[] toArray() 返回一个包含此流的元素的数组

在 Java 中,IntStream 是一个用于处理基本类型 int 的流。IntStream 提供了许多用于操作和处理 int 类型数据的方法。以下是一些 IntStream 中常用的方法:

  1. forEach(IntConsumer action):对流中的每个元素执行指定的操作。
  2. sum():返回流中所有元素的和。
  3. average():返回流中所有元素的平均值。
  4. min():返回流中所有元素的最小值。
  5. max():返回流中所有元素的最大值。
  6. count():返回流中元素的数量。
  7. filter(IntPredicate predicate):根据指定的条件过滤流中的元素。
  8. map(IntUnaryOperator mapper):对流中的每个元素执行指定的映射操作。
  9. distinct():去除流中重复的元素,返回一个去重后的流。
  10. sorted():对流中的元素进行排序。
  11. limit(long maxSize):截取流中的前 maxSize 个元素。
  12. skip(long n):跳过流中的前 n 个元素。
  13. reduce(int identity, IntBinaryOperator op):对流中的元素进行归约操作,返回一个结果。
  14. anyMatch(IntPredicate predicate):判断流中是否存在任意一个元素满足指定条件。
  15. allMatch(IntPredicate predicate):判断流中是否所有元素都满足指定条件。
  16. noneMatch(IntPredicate predicate):判断流中是否所有元素都不满足指定条件。

这些方法可以帮助我们在处理 int 类型数据的流时进行各种操作,如过滤、映射、归约、排序等。通过灵活运用这些方法,可以方便地对 IntStream 进行处理和操作。

1
2
3
4
5
6
7
//需求1:将集合中的字符串数据转换为整数之后在控制台输出
list.stream().map(Integer::parseInt).forEach(System.out::println);
list.stream().mapToInt(Integer::parseInt).forEach(System.out::println);

//需求2:将集合中的字符串数据转换为整数之后在控制台输出 元素和
int result = list.stream().mapToInt(Integer::parseInt).sum();
System.out::println(result);

(3)Stream流的常见终结操作方法

forEach、count

void forEach(Consumer action):对此流的每个元素执行操作
Consumer接口中的方法 —> void accept(T t):对给定的参数执行此操作
long count():返回此流中的元素数

1
2
3
4
5
//需求1:把集合中的元素在控制台输出
List.stream().forEach(System. out::println);
//需求2: 统计集合中有几个以张开头的元素,并把统计结果在控制台输出
long count = list.stream().filter(s -> s.startswith("张")).count();
System.out.printIn(count);

Stream流的收集操作

对数据使用Stream流的方式操作完毕后,我想把流中的数据收集到集合中,该怎么办呢?

Stream流的收集方法:
R collect(Collector collector)
但是这个收集方法的参数是一个Collector接口

工具类Collectors提供了具体的收集方式:
public static< T > Collector toList(): 把元素收集到List集合中
public static< T > Collector toSet(): 把元素收集到Set集合中
public static Collector toMap(Function keyMapper,Function valueMapper): 把元素收集到Map集合中

Collectors.toList()

1
2
3
4
5
6
7
8
//需求1:得到名字为3个字的流
Stream<String> listStream = list.stream().filter(s -> s.length() == 3);
//需求2:把使用stream流操作完毕的数据收集到List集合中并追历
List<String> names = listStream.collect(Collectors.tolist());

for(String name : names){
System.out.println(name);
}

Collectors.toSet()

1
2
3
4
5
6
7
8
//需求3:得到年龄大于25的流
Stream<Integer> setStream = set.stream().filter(age -> age > 25);
//需求4:把使用stream流操作完毕的数据收集到Set集合中并遍历
Set<Integer> ages = setStream.collect(Collectors.toSet());

for(Integer age : ages) {
System.out.println(age);
}

Collectors.toMap(Function keyMapper,Function valueMapper)

1
2
3
4
5
6
7
8
9
10
11
12
13
//定义一个字符串数组,每一个字符串数据由姓名数据和年龄数据组合而成
String[] strArray = {"林青霞,30""张曼玉,35""王祖贤,33""柳岩,25"};

//需求5:得到字符串中年龄数据大于28的流
Stream<String> arrayStream = Stream.of(strArray).filter(s -> Integer,parseInt(s.split(",")[1]) > 28);
//需求6:把使用stream流操作完毕的数据收集到Map集合中并遍历,字符串中的姓名作键,年龄作值
Map<String,Integer> map = arrayStream.collect(Collectors.toMap(s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1])));

Set<String> keySet = map.keySet();
for (String key : keySet) {
Integer value = map.get(key);
System.out.println(key + "," + value);
}

Collectors.groupingBy
方法是一个非常常用的收集器,用于根据指定的分类函数流中的元素进行分组
该方法接受一个分类函数作为参数,将流中的元素按照分类函数的返回值进行分组
并返回一个 Map,其中键是分类函数的返回值,值是对应分类的元素列表

1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public List<List<String>> groupAnagrams(String[] strs) {
return new ArrayList<>(Arrays.stream(strs)
.collect(Collectors.groupingBy(str -> {
// 返回 str 排序后的结果。
// 按排序后的结果来grouping by,算子类似于 sql 里的 group by。
char[] array = str.toCharArray();
Arrays.sort(array);
return new String(array);
})).values());
}
}
Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2023-2025 Annie
  • Visitors: | Views:

嘿嘿 请我吃小蛋糕吧~

支付宝
微信