Java 8 API添加了一个新的抽象称为流Stream,可以配合Lambda表达式,简化集合和数组操作。
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
Stream流思想的直观理解:
主要的使用方法分为三步:
- 获取Stream流对象
- 中间方法
- 终结方法
此外,还有将Stream流对象转回到集合的收集操作。
获取Stream流对象
集合获取Stream流对象
集合获取Stream流对象,对于 List 和 Set 集合:
List<String> list = new ArrayList<String>();
list.add("张三丰");
list.add("张无忌");
list.add("张翠山");
list.add("王二麻子");
list.add("张良");
list.add("谢广坤");
list.stream()...... // 后面是中间方法和终结方法
Set<String> set = new HashSet<String>();
set.add("张三丰");
set.add("张无忌");
set.add("张翠山");
set.add("王二麻子");
set.add("张良");
set.add("谢广坤");
set.stream()...... // 后面是中间方法和终结方法
对于 Map 集合,需要间接获取,使用 entrySet 方法:
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("张三丰", 100);
map.put("张无忌", 35);
map.put("张翠山", 55);
map.put("王二麻子", 22);
map.put("张良", 30);
map.put("谢广坤", 55);
map.entrySet().stream()...... // 后面是中间方法和终结方法
数组获取Stream流对象
数组获取Stream流对象,使用Arrays数组工具类中的静态方法
int[] arr1 = {11, 22, 33};
double[] arr2 = {11.1, 22.2, 33.3};
Arrays.stream(arr1)...... // 后面是中间方法和终结方法
Arrays.stream(arr2)...... // 后面是中间方法和终结方法
零散数据获取 Stream 流对象
零散数据获取Stream流对象,使用Stream类的静态方法
Stream.of(1, 2, 3, 4, 5, 6)...... // 后面是中间方法和终结方法
Stream.of("张三", "李四", "王五", "赵六")...... // 后面是中间方法和终结方法
Stream流的中间方法
注意事项:流对象已经被消费过(使用过终结方法),就不允许再次消费
以例子说明上述方法的具体功能:
// 需求: 将集合中以 【张】 开头的数据,过滤出来并打印在控制台
ArrayList<String> list = new ArrayList<String>();
list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌");
list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3)
.forEach(s -> System.out.println(s));
System.out.println("-------------------------------------");
// 需求1: 取前3个数据在控制台输出
list.stream().limit(3).forEach(s -> System.out.println(s));
System.out.println("-------------------------------------");
// 需求2: 跳过3个元素, 把剩下的元素在控制台输出
list.stream().skip(3).forEach(s -> System.out.println(s));
System.out.println("-------------------------------------");
// 需求3: 跳过2个元素, 把剩下的元素中前2个在控制台输出
list.stream().skip(2).limit(2).forEach(s -> System.out.println(s));
System.out.println("-------------------------------------");
// 需求4: 取前4个数据组成一个流
Stream<String> s1 = list.stream().limit(4);
// 需求5: 跳过2个数据组成一个流
Stream<String> s2 = list.stream().skip(2);
// 需求6: 合并需求4和需求5得到的流, 并把结果在控制台输出
Stream<String> s3 = Stream.concat(s1, s2);
// s3.forEach(s -> System.out.println(s));
System.out.println("-------------------------------------");
// 需求7: 合并需求4和需求5得到的流, 并把结果在控制台输出,要求字符串元素不能重复
s3.distinct().forEach(s -> System.out.println(s));
Stream流终结方法
上面已经使用过 forEach 方法,下面展示 count 方法
long count = Stream.of(1, 2, 3, 4, 5, 6).filter(s -> s % 2 == 0).count();
System.out.println(count);
Stream流收集操作
对于 List 和 Set 集合:
List<Integer> list = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).filter(s -> s % 2 == 0).collect(Collectors.toList());
System.out.println(list);
Set<Integer> set = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).filter(s -> s % 2 == 0).collect(Collectors.toSet());
System.out.println(set);
对于 Map 集合:
ArrayList<String> list = new ArrayList<>();
list.add("张三,23");
list.add("李四,24");
list.add("王五,25");
Map<String, Integer> map = list.stream().filter(s -> Integer.parseInt(s.split(",")[1]) >= 24)
.collect(Collectors.toMap(s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1])));
System.out.println(map);