Featured image of post java高级之Stream

java高级之Stream

本文阅读量

Stream

是jdk8开始新增的一套Api(java.util.stream.*),可以用于操作集合或者数组的数据

对比集合或数组的优势:

Steam流大量的结合了Lambda的语法风格来编程,提供了一种更强大,更加简单的方式操作集合或数组中的数据,代码更简洁,可读性更好

体验

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
// 获取以张开头的,并且是3个字的(常规api解决)
List<String> newList = new ArrayList<>();
for(String s: list){
  if(s.startsWith("张") && s.length()==3)
    newList.add(s);
}
// stream流解决
List<String> newList2 = list.stream().filter(s->s.startsWith("张") && s.length()==3).collection(Collectors.toList());

使用步骤

  1. 获取Stream流list.stream(),Stream流代表一条流水线,并能与数据源建立连接
  2. 使用流水线各种方法对数据进行处理(过滤(filter),排序(),去重())、计算,得到最终结果
  3. 将处理的结果,遍历、统计、收集到一个新集合中返回

获取stream流

public interface Stream<T>

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
Collection<String> list = new ArrayList<>();
Collection.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰");
// 1、获取集合的Stream流
// default Stream<E> stream()
Stream<String> s1 = list.stram();

// 2、获取Map集合的stream流
Map<String,Integer> map = new HashMap<>();
// 2.1获取键流
Stream<String> keys = map.keySet().stream();
// 2.2获取值流
Stream<String> values = map.values().stream();
// 2.3获取键值对流
Stream<Map.Entry<String,Integer>> entrys = map.entrySet().stream();
  

String[] names = {"张无忌","周芷若","赵敏"};
// 3、获取数组的Stream流
//public static <T> Stream<T> stream(T[] array)
Stream<String> as1 = Arrays.stream(names);
//public static Stream<T> of(T... values)
Stream<String> as2 = Stream.of(names);

Stream流常用方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
List<String> list = new ArrayList<>();
Collection.addAll(list,"张无忌","周芷若","赵敏","张强","张三丰");

// 1、过滤方法
list.stream().filter(s->s.startsWith("张") && s.length()==3).forEach(System.out::println);

// 2、排序方法
List<Movie> movies = new ArrayList<>();
Movies.add(new Movie("摔跤吧,爸爸",9.5,"阿米尔汗"));
...
// 方式1:对象类实现Comparable接口,指定比较规则
movies.stream().sorted().forEach(System.out::println);
// 方式2:
movies.steam().sorted((m1,m2)-> Double.compare(m2.getScore(),m1.getScore())).forEach(System.out::println);

// 3、排序后使用limit取前几个
movies.stream().sorted().limit(3).forEach(System.out::println);

// 4、跳过前几个 skip
movies.stream().sorted().skip(3).forEach(System.out::println);

// 5、去重 distinct
// 前提:需要重写对象类的hashCode和equals方法
movies.stream().sorted().distinct().forEach(System.out::println);

// 6、把流上的数据加工成新数据
movies.steam().map(m -> m.getName() + "==>" + m.getScore()).forEach(System.out::println);

// 7、合并流,把两个流合并起l
Stream<String> s1 = Stream.of("张三","李四","西门吹雪");
Stream<String> s2 = Stream.of("楚留香","石观音");
// public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
Steam<String> allStream = Stream.concat(s1,s2);

Stream<Integer> s3 = Stream.of(12,11,43);
Steam<Object> allStream = Stream.concat(s1,s3);

Stream流常见终结方法

终结方法:是调用完成后,不会返回新的stream流了,没法继续使用stream流了

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
List<Movie> movies = new ArrayList<>();
Movies.add(new Movie("摔跤吧,爸爸",9.5,"阿米尔汗"));
...
  
// 1、forEach
movies.stream().forEach(System.out::println);

// 2、count
long count = movies.stream().skip(2).count(); // 总数-2

//3、取最大值
Optional<Movie> max = movies.steam().max(((o1,o2)->Double.compare(o1.getScore(),o2.getScore())));
Movie m = max.get();
// 简化
Movie max  = movies.steam().max(((o1,o2)->Double.compare(o1.getScore(),o2.getScore()))).get();
// 最小值
Movie min  = movies.steam().min(((o1,o2)->Double.compare(o1.getScore(),o2.getScore()))).get();

收集stream流

就是把stream流操作后的的结果转回到集合或者数组中去返回

stream,只是我们一种手段,一种方便操作集合/数组的手段

而我们需要的结果是:集合/数组(开发的目的)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
Stream<String> stream = list.stream(); // 流只能使用一次

// 1、收集到list集合   获取以张开头的,并且是3个字的(常规api解决)
List<String> newList = stream.filter(s->s.startsWith("张") && s.length()==3).collection(Collectors.toList());
Stream<String> stream2 = list.stream(); // 流只能使用一次
List<String> newList = stream2.filter(s->s.startsWith("张") && s.length()==3).toList(); // jdk16才支持

// 2、收集到set集合
Stream<String> stream3 = list.stream(); // 流只能使用一次
Set<String> newset = stream3.filter(s->s.startsWith("张") && s.length()==3).collection(Collectors.toSet());


// 4、收集stream流:把流中的数据恢复到集合或数组中去
// 收集到数组中去
Stream<String> stream4 = list.stream(); // 流只能使用一次
Object[] objects = stream4.filter(s->s.startsWith("张") && s.length()==3).toArray();

// 为什么集合还是能转换成字符串集合,如:Set<String>,而不转化成Object对象呢?
// 数组是强类型,数组类型是固定死的,集合是泛化的,最终还是Object,引用String集合也能接其他类型,而String数组只能接收字符串

// 收集到map集合(拓展)
List<Movie> movies = new ArrayList<>();
Movies.add(new Movie("摔跤吧,爸爸",9.5,"阿米尔汗"));
...
Map<String,Doubel> map = movies.steam().limit(3).collect(Collectors.toMap(m1-> m1.getName(), m2->m2.getScore(),(v1,v2)->v1));// (v1,v2)->v1)避免重复,如果重复了,前面的覆盖后面,(v1,v2)->v2:后面覆盖前面
使用 Hugo 构建
主题 StackJimmy 设计