Stream流
简洁优雅,可配合Lambda连用。Stream流把真正的函数式风格引入到Java中
举个例子:输出集合list中的开头为肘的长度为2的元素
public class StreamDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("肘子");
list.add("红肠");
list.add("玉米肠");
list.add("冻豆腐");
list.add("肘");
list.add("肘");
ArrayList<String> zhouList = new ArrayList<>();
for (String s : list) {
if (s.startsWith("肘")) {
zhouList.add(s);
}
}
ArrayList<String> threeList = new ArrayList<>();
for (String s : zhouList) {
if (s.length() == 2) {
threeList.add(s);
}
}
for (String s : threeList) {
System.out.println(s);
}
// 使用Stream流方式
// list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length()==2).forEach(s -> System.out.println(s));
// 可直接阅读代码的字面意思,展示无关逻辑方式的语义:生成流、过滤开头为肘、过滤长度为2、逐一打印
list.stream().filter(s -> s.startsWith("肘")).filter(s -> s.length() == 2).forEach(System.out::println);
}
}
//输出结果
//肘子
//肘子
Stream流的使用
Stream流可分为生成流,中间操作,终结操作。
生成流
可通过数据源(集合、数组等)生成流。
Stream流的常见生成方式
- Collection体系的集合可以使用默认方法stream()生成流 default Stream stream()
- Map体系的集合间接的生成流
- 数组可以通过Stream接口的静态方法of(T…values)生成流
中间操作
一个流后面可以跟随零个或多个中间操作,其目的主要是打开流,做出某种程度的数据过滤/映射,然后返回一个新的流,交给下一个操作使用。都是Stream接口中的方法。
Stream流中的常见的中间操作方法
- Stream filter(Predicate predicate):用于对流中的数据进行过滤
Predicate接口中的方法 boolean test(T t):对给定的参数进行判断,返回一个布尔值 - Stream limit(long maxSize):返回此流中的元素组成的流,截取前指定参数个数的数据
- Stream skip(long n):跳过指定参数个数的数据,返回由该流的剩余元素组成的流
- static Stream concat(Stream a, Stream b):合并a和b两个流为一个流
- Stream distinct():返回由该流的不同元素(根据Object.equals(Object) )组成的流
- Stream sorted():返回由此流的元素组成的流,根据自然顺序排序
- Stream sorted(Comparator comparator):返回由该流的元素组成的流,根据提供的Comparator进行排序
- Stream map(Function mapper):返回由给定函数应用于此流的元素的结果组成的流
Function接口中的方法 R apply(T t) - IntStream mapToInt(ToIntFunction mapper):返回一个IntStream其中包含将给定函数应用于此流的元素的结果
IntStream:表示原始 int 流
ToIntFunction接口中的方法 int applyAsInt(T value)
小例子:
public class Actor {
String name;
public Actor(String name) {
this.name = name;
}
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class ActorDemo {
public static void main(String[] args) {
ArrayList<String> manList = new ArrayList<String>();
manList.add("小雷");
manList.add("陈小凡");
manList.add("朱小磊");
manList.add("李小白");
manList.add("王小易");
ArrayList<String> womenList = new ArrayList<String>();
womenList.add("小敏");
womenList.add("林清");
womenList.add("林红");
womenList.add("林数");
Stream<String> man = manList.stream().filter(s -> s.length() == 3).limit(3);
Stream<String> women = womenList.stream().filter(s -> s.startsWith("林")).skip(1);
Stream<String> concat = Stream.concat(man, women);
concat.map(Actor::new).forEach(s -> System.out.println(s.getName()));
}
}
//输出结果
//陈小凡
//朱小磊
//李小白
//林红
//林数
public class InterStreamDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("spring");
list.add("sum");
list.add("winter");
list.add("autumn");
list.add("autumn");
Stream<String> first = list.stream().limit(2).filter(s -> s.startsWith("s"));
Stream<String> last = list.stream().skip(3);
// Stream.concat(first,last).sorted().forEach(System.out::println);
Stream<String> concat = Stream.concat(first, last);
concat.sorted((s1,s2) -> {
int num = s1.length()-s2.length();
int num2 = num == 0? s1.compareTo(s2):num;
return num2;
}).distinct().forEach(System.out::println);
}
}
//输出结果
//sum
//autumn
//spring
终结操作方法
一个流只能有一个终结操作,当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作
Stream流的常见终结操作方法
- void forEach(Consumer action):对此流的每个元素执行操作
Consumer接口中的方法 void accept(T t):对给定的参数执行此操作 - long count():返回此流中的元素数
小例子:
public class MapStreamDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("123");
list.add("1");
list.add("34");
list.add("45");
list.add("21");
list.stream().map(Integer::parseInt).forEach(System.out::println);
System.out.println("----------------");
int sum = list.stream().mapToInt(Integer::parseInt).sum();
System.out.println(sum);
}
}
//输出结果
//123
//1
//34
//45
//21
//----------------
//224
Stream流的收集操作
对数据使用Stream流的方式操作完毕后,把流中的数据收集到集合中,可有一下的方法。
Stream流的收集方法
- R collect(Collector collector)
- 但是这个收集方法的参数是一个Collector 接口
工具类Collectors提供了具体的收集方式
- public static Collector toList():把元素收集到List集合中
- public static Collector toSet():把元素收集到Set集合中
- public static Collector toMap(Function keyMapper,Function valueMapper):把元素收集到Map集合中
public class CollectionStreamDemo {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("春天");
list.add("煎饼果子");
list.add("小笼包");
list.add("地三鲜");
Stream<String> stringStream = list.stream().filter(s -> s.length() > 2);
List<String> collect = stringStream.collect(Collectors.toList());
for (String food : collect) {
System.out.println(food);
}
}
}
//输出结果
//煎饼果子
//小笼包
//地三鲜
Set<Integer> set = new HashSet<Integer>();
set.add(10);
set.add(10);
set.add(20);
set.add(34);
set.add(51);
System.out.println("------------");
Stream<Integer> stream1 = set.stream().filter(s -> s > 25);
Set<Integer> collect1 = stream1.collect(Collectors.toSet());
for (Integer collect11 : collect1) {
System.out.println(collect11);
}
//输出结果
//34
//51
String[] strAttay = {"小张,34","小李,31","小数,41","小巩,56","小薇,24"};
Stream<String> stringStream1 = Stream.of(strAttay).filter(s -> Integer.parseInt(s.split(",")[1]) > 28);
Map<String, Integer> collect2 = stringStream1.collect(Collectors.toMap(s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1])));
Set<String> keySet = collect2.keySet();
for (String keset : keySet) {
Integer integer = collect2.get(keset);
System.out.println(keset+","+integer);
}
//输出结果
//小巩,56
//小李,31
//小张,34
//小数,41